目前是50pts,后面五个点wa了
#include<bits/stdc++.h>
using namespace std;
/*
基环树森林上dp
1.找环
2.非环做最大权独立集dp
3.环上,偶环有两种情况,奇环有n中情况(枚举间隔两个的)
注意可能有重边
*/
#define N 1000005
int n,_fa[N],book[N],st[N],top,loop[N],lsiz;
long long w[N],f[N][2],odd[N],even[N];//odd/even:统计基环树答案时前缀的 必不取偶答案/必不取奇答案
vector<int>e[N];
bitset<N>onloop;
void dfs1(int x,int fa){
st[++top]=x;
book[x]=top;
for(auto v:e[x]){
if(v==fa)continue;
if(!book[v]){
dfs1(v,x);
}
else{
for(int i=book[v];i<=top;i++){
loop[++lsiz]=st[i];
}
}
}
--top;
}
void dfs2(int x,int fa){
f[x][0]=0;
f[x][1]=w[x];
for(auto v:e[x]){
if(v==fa||onloop[v])continue;
dfs2(v,x);
f[x][1]+=f[v][0];
f[x][0]+=max(f[v][0],f[v][1]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%d",&w[i],&_fa[i]);
if(_fa[_fa[i]]==i)continue;//去重边
e[i].push_back(_fa[i]);
e[_fa[i]].push_back(i);
}
long long ans=0;
for(int i=1;i<=n;i++){
if(!book[i]){
top=lsiz=0;
dfs1(i,0);
if(lsiz){
for(int j=1;j<=lsiz;j++){
onloop[loop[j]]=true;
}
for(int j=1;j<=lsiz;j++){
dfs2(loop[j],0);
}
for(int j=1;j<=lsiz;j++){//必不取偶
if(j&1){
odd[j]=odd[j-1]+max(f[loop[j]][1],f[loop[j]][0]);
}
else{
odd[j]=odd[j-1]+f[loop[j]][0];
}
}
for(int j=1;j<=lsiz;j++){//必不取奇
if(j&1){
even[j]=even[j-1]+f[loop[j]][0];
}
else{
even[j]=even[j-1]+max(f[loop[j]][1],f[loop[j]][0]);
}
}
if(lsiz&1){
long long maxn=0;
for(int j=1;j<=lsiz;j++){//j和j+1必不放("lsiz和1"也可用通式)
if(j&1){
maxn=max(maxn,even[j]+odd[lsiz]-odd[j]);
}
else{
maxn=max(maxn,odd[j]+even[lsiz]-even[j]);
}
}
if(lsiz==1)maxn=max(maxn,odd[lsiz]);
ans+=maxn;
}
else{
ans+=max(odd[lsiz],even[lsiz]);
}
}
else{
dfs2(i,0);
ans+=max(f[i][0],f[i][1]);
}
}
}
printf("%lld",ans);
return 0;
}