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;
}
posted @ 2019-10-15 21:02  prestige  阅读(85)  评论(0编辑  收藏  举报