1. 程式人生 > 實用技巧 >P2607 [ZJOI2008]騎士(基環樹)

P2607 [ZJOI2008]騎士(基環樹)

類似沒有上司的舞會,找到環上一點,將環斷開,強制是否選擇root,做樹形dp

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+1e5;
int h[N],ne[N*2],e[N*2],idx;
int fa[N];
int val[N];
int st[N];
ll f[N][2];
int find(int u){
    st[u] = 1;
    if(st[fa[u]]) return fa[u];
    else return find(fa[u]);
}
void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int u,int rt,int x){ f[u][0]=0,f[u][1]=val[u]; st[u]=1; for(int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==rt) continue; dfs(j,rt,x); f[u][0]+=max(f[j][1],f[j][0]); f[u][
1]+=f[j][0]; } if(u==x) f[u][1]=-1e18; } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; int n; cin>>n; for(i=1;i<=n;i++){ int a,b; cin>>val[i]>>b; add(b,i); fa[i]=b; } ll ans=0; ll res
=0; for(i=1;i<=n;i++){ if(!st[i]){ int u=find(i); dfs(u,u,0); ans=f[u][0]; dfs(u,u,fa[u]); ans=max(f[u][1],ans); res+=ans; } } cout<<res<<endl; return 0; }
View Code