这题是pxr讲过的题,我又想起了那段日子。刚刚转到4班(壮哉我大四班)。当时和1023一样,听懂后就没有管了。前几天做了几个拆环的dp,所以就想到还有这个题,于是就过来把它切了。不知道pxr出国准备得怎么样了。
这个题就是拆环,然后像没有上司的舞会那样进行一次dp就好了。注意,这个题是多个块。。。。。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 2000200
#define sint long long
int read()
{
int res;char c;
while(c=getchar(),c<'0'||c>'9');
res=c-'0';
while(c=getchar(),c>='0'&&c<='9')
res=res*10+c-'0';
return res;
}
int first[maxn],to[maxn],n,en,val[maxn],next[maxn];
long long dp[maxn][2],ans;
int vis[maxn],st,ed,tot,tot2,flag;
void add(int a,int b)
{
en++;
to[en]=b;
next[en]=first[a];
first[a]=en;
}
void dfs1(int now,int fa)
{
vis[now]=1;
for(int i=first[now];i;i=next[i])
{
int v=to[i];
if(v==fa) continue;
if(!vis[v])
{
dfs1(v,now);
}
else
{
st=now;ed=v;
}
}
}
void dfs(int now,int fa)
{
dp[now][1]=val[now];
dp[now][0]=0;
for(int i=first[now];i;i=next[i])
{
int v=to[i];
if(v==fa||i==tot||i==tot2) continue;
dfs(v,now);
dp[now][1]+=dp[v][0];
if(v!=ed)
{
dp[now][0]+=max(dp[v][0],dp[v][1]);
}
else
{
dp[now][0]+=dp[v][0];
}
}
}
void solve()
{
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
flag=0;
dfs1(i,0);
for(int j=first[st];j;j=next[j])
if(to[j]==ed)
{
tot=j;
}
for(int j=first[ed];j;j=next[j])
if(to[j]==st)
{
tot2=j;
}
dfs(st,0);
sint ans1=max(dp[st][0],dp[st][1]);
swap(st,ed);
dfs(st,0);
ans1=max(max(ans1,dp[st][0]),dp[st][1]);
ans+=ans1;
}
}
}
int main()
{
//freopen("knight3.in","r",stdin);
scanf("%d",&n);
int a,b;
for(int i=1;i<=n;i++)
{
val[i]=read();a=read();
add(a,i);
add(i,a);
}
solve();
printf("%lld\n",ans);
return 0;
}