P2607 [ZJOI2008]骑士
题面:https://www.luogu.org/problem/P2607
没有上司的舞会+环套树(破环为链)。。。
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<vector>
using namespace std;
const int N=2000005;
int n,m,cnt,root,head[N],val[N],vis[N],fa[N];
long long f[N][2],ans;
struct Node{
int u,v,nxt;
}edge[N*2];
void add(int u,int v){
++cnt;
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
void dfs(int u){
vis[u]=1;
f[u][0]=0;
f[u][1]=val[u];
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].v;
if(v!=root){
dfs(v);
f[u][0]+=max(f[v][1],f[v][0]);
f[u][1]+=f[v][0];
}
else{
f[v][1]=-N;
}
}
}
void find_circle(int x){
vis[x]=1;
root=x;
while(!vis[fa[root]]){
root=fa[root];
vis[root]=1;
}
dfs(root);
long long t=max(f[root][0],f[root][1]);
root=fa[root];
dfs(root);
ans+=max(t,max(f[root][0],f[root][1]));
return;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x;
scanf("%d%d",&val[i],&x);
add(x,i);
fa[i]=x;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
find_circle(i);
}
}
printf("%lld\n",ans);
return 0;
}