n个点n条边,虽然不是一个树但还是很接近了,想象一下如果只有n-1条边的情况那么就可以直接套最大独立子集了,so easy。但是这一道题居然环,先别怕,因为只是多了一条边所以即使构成环那么最多只有一个环,只需要找出来,断掉一条边就是一个树了,然后以这条边两边的节点为根做最大独立子集,规定两个节点均不可选情况下的最大值,最后,注意题目中的可能是一个森林
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 1000020
#define LL long long
using namespace std;
LL n,head[maxn],tot,s,t,val[maxn],f[maxn][2],vis[maxn],edg;
LL ans;
void read(LL& x){
char c=getchar();x=0; LL flag=1;
for(;c>'9'||c<'0';c=getchar())if(c=='-')flag=-1;
for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
x*=flag;
}
struct edge{LL next,v;}e[maxn*2];
void adde(LL a,LL b){
e[tot].v=b,e[tot].next=head[a];head[a]=tot++;
}
void dfs1(LL u,LL fa){
vis[u]=1;
for(LL v,i=head[u];i!=-1;i=e[i].next ){
v=e[i].v;if(v==fa)continue;
if(vis[v])s=v,t=u,edg=i;
else dfs1(v,u);
}
}
void dfs2(LL u,LL fa){
f[u][0]=0,f[u][1]=val[u];
for(LL v,i=head[u];i!=-1;i=e[i].next){
v=e[i].v;if(v==fa||i==edg||(i^1)==edg)continue;
dfs2(v,u);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
}
}
int main(){
read(n);
memset(head,-1,sizeof(head));
for(LL a,i=1;i<=n;i++){
read(val[i]),read(a);
adde(i,a),adde(a,i);
}
LL x;
for(LL i=1;i<=n;i++){
if(!vis[i]){
dfs1(i,i);dfs2(s,s);
x=f[s][0];
dfs2(t,t);
ans+=max(x,f[t][0]);
}
}
printf("%lld",ans);
return 0;
}