思路就是每次找环断开,在当前连通块里分别以两个断点做dp
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1000010;
int n,r1,r2,de;
int val[N];
int cnt,head[N],nxt[N * 2],to[N * 2];
long long ans,f[N][2];
bool vis[N];
void add(int u,int v) {
cnt ++;
to[cnt] = v;
nxt[cnt] = head[u];
head[u] = cnt;
}
void circle(int x,int fa) {
vis[x] = 1;
for(int i=head[x] ; i ; i=nxt[i]) {
int v = to[i];
if(v == fa) continue;
if(vis[v]) {
r1 = x,r2 = v;
continue;
}
circle(v,x);
}
}
void dfs(int x,int fa) {
f[x][0] = 0;
f[x][1] = val[x];
for(int i=head[x] ; i ; i=nxt[i]) {
int v = to[i];
if(v == fa) continue;
if((x == r1 && v == r2) || (x == r2 && v == r1)) continue;
dfs(v,x);
f[x][1] += f[v][0];
f[x][0] += max(f[v][1],f[v][0]);
}
}
int main(){
scanf("%d",&n);
for(int i=1 ; i<=n ; i++) {
scanf("%d",&val[i]);
int v;
scanf("%d",&v);
add(v,i);
add(i,v);
}
for(int i=1 ; i<=n ; i++) {
if(vis[i]) continue;
r1 = 0,r2 = 0;
circle(i,0);
long long tmp = 0;
dfs(r1,0);
tmp = f[r1][0];
dfs(r2,0);
ans += max(tmp,f[r2][0]);
}
printf("%lld",ans);
}