根据关系建立一个无向图,每次找到一个环。
对于环上的一条边e,取两边的点u,v,各做一次树形dp。
对于g[x]表示不取x时最大值,对于f[x]表示取x时最大值。
在做dp时要将边e断开不走。取g[u]与f[u]的最大值加入答案中。
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
const int N=1000005;
int n;
ll f[N],g[N],ans;
struct node{
int to,nxt;
}ta[N<<1];
bool vis[N];
int pre[N];
int a[N],x,tot=1;
int U,V,E;
inline void add(int u,int v)
{
ta[++tot].to=v;
ta[tot].nxt=pre[u];
pre[u]=tot;
}
void dfs(int x,int pr)
{
int p;
vis[x]=1;
for (p=pre[x];p;p=ta[p].nxt)
if ((p^1)==pr) continue;
else
{
if (vis[ta[p].to])
{
U=x;
V=ta[p].to;
E=p;
continue;
}
dfs(ta[p].to,p);
}
}
void tdp(int x,int pr,int bre)
{
int p;
f[x]=a[x];
g[x]=0;
for (p=pre[x];p;p=ta[p].nxt)
{
if (p==bre||(p^1)==bre) continue;
if ((p^1)==pr) continue;
tdp(ta[p].to,p,bre);
f[x]+=g[ta[p].to];
g[x]+=max(f[ta[p].to],g[ta[p].to]);
}
}
int main()
{
register int i,j;
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d %d",&a[i],&x);
add(i,x);
add(x,i);
}
for (i=1;i<=n;i++)
{
if (!vis[i])
{
dfs(i,0);
tdp(U,0,E);
ll t=g[U];
tdp(V,0,E);
t=max(t,g[V]);
ans+=t;
}
}
printf("%lld",ans);
return 0;
}