传送门biu~
如果是一棵树,答案显而易见。用f[i]代表以i为根的子树中选择i这个点的最大值,g[i]是不选择i这个点的最大值。递归求解即可。
对于一棵环套树,我们可以从环中任意选择一条边(u,v),u和v不能同时选择。我们可以先计算不选v的最大值,再计算不选u的最大值,最后取max即可。
#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int n,m,Rt1[N],Rt2[N],v[N],fa[N],head[N],nex[N<<1],to[N<<1],tp;
long long g[N],f[N],ans;
int search(int x){return fa[x]==x?x:fa[x]=search(fa[x]);}
inline void add(int x,int y){
nex[++tp]=head[x];
head[x]=tp;
to[tp]=y;
}
void dfs(int x,int father){
f[x]=v[x];g[x]=0;
for(int i=head[x];i;i=nex[i]){
if(to[i]==father) continue;
dfs(to[i],x);
g[x]+=max(f[to[i]],g[to[i]]);
f[x]+=g[to[i]];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1;i<=n;++i){
int x;
scanf("%d%d",&v[i],&x);
if(search(i)^search(x)){
add(i,x),add(x,i);
fa[fa[i]]=fa[x];
}
else Rt1[++m]=i,Rt2[m]=x;
}
for(int i=1;i<=m;++i){
long long tmp=0;
dfs(Rt1[i],0); tmp=max(tmp,g[Rt1[i]]);
dfs(Rt2[i],0); tmp=max(tmp,g[Rt2[i]]);
ans+=tmp;
}
printf("%lld\n",ans);
return 0;
}