Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各
界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境
中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一
个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一
些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出
征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有
的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的
情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战
斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。
这是一个树,加上一条边。
树上相邻的点不能选。
所以我们就可以把树上的环破坏。
找到环,去掉一条边。记录这条边的两个节点,
假设分别是 U V,
我们可以分别以 U V 为根节点。
U 不选,查找可以得到的最大值,
V不选,查找可以得到的最大值。
两个最大值,去max。
f[x] 代表选择 x 点的子树最大值。,
g[x] 代表不选x 点的子树最大值。
#include <bits/stdc++.h>
#define mem(x,v) memset(x,v,sizeof(x))
#define go(i,a,b) for (int i = a; i <= b; i++)
#define og(i,a,b) for (int i = a; i >= b; i--)
using namespace std;
typedef long long LL;
const int N = 3e6+10;
int Head[N],Next[N],to[N],cnt = -1;
LL f[N],g[N],val[N];
bool vis[N];
int U,V,E;
void Add(int u, int v){
Next[++cnt] = Head[u];
Head[u] = cnt;
to[cnt] = v;
Next[++cnt] = Head[v];
Head[v] = cnt;
to[cnt] = u;
}
void dfs(int u, int fa){
vis[u] = 1;
for (int i = Head[u]; i != -1; i = Next[i]){
int v = to[i];
if (v == fa) continue;
if (vis[v]){
U = u;
V = v;
E = i;
continue;
}
dfs(v,u);
}
return;
}
void solve(int u, int fa){
f[u] = val[u]; g[u] = 0;
for (int i = Head[u]; i != -1; i = Next[i]){
int v = to[i];
if ((i==E)||(v == fa)||((i^1) == E)) continue;
solve(v,u);
f[u] += g[v];
g[u] += max(f[v],g[v]);
}
}
int main(){
int n;
scanf("%d",&n);
mem(Head,-1);
go(i,1,n){
int x,y;
scanf("%d%d",&x,&y);
val[i] = x;
Add(i,y);
}
LL ans = 0;
go(i,1,n)
if (!vis[i]){
dfs(i,0);
solve(U,0);
LL temp = g[U];
solve(V,0);
temp = max(temp,g[V]);
ans += temp;
}
cout<<ans<<endl;
return 0;
}