和<没有上司的舞会>一样,但树上多了条边

 

 断掉环上一条边,两个点分别做dp ,取max

 

#include <iostream>
#include <algorithm>
using namespace std ;
 const int N=1e6+5,M=2*N;
 #define int long long
 int n,vis[N],a[N];
 int rt1,rt2,f[N][2];
 int nxt[M],go[M],hd[N],all=1;
 int e;
 
 void add(int x,int y){
 	go[++all]=y,nxt[all]=hd[x],hd[x]=all;
 }
 void find(int x,int fa){
 	vis[x]=1;
 	int i,y;
 	for(i=hd[x];i;i=nxt[i]){
 		y=go[i]; if(y==fa) continue;
 		if(vis[y]){
 			rt1=x,rt2=y; e=i; break;
 		}
 		find(y,x);
 	}
 }
 void dp(int x,int fa){
 	int i,y;
 	vis[x]=1;
 	f[x][1]=a[x];
 	f[x][0]=0;
 	for(i=hd[x];i;i=nxt[i]){
 		y=go[i]; if(y==fa||i==e||(i^1)==e) continue;
 		dp(y,x);
 		f[x][0]+=max(f[y][1],f[y][0]);
 		f[x][1]+=f[y][0];
 	}
 }
 signed main(){
 	int i,x,t1,t2,ans=0;
 	cin>>n;
 	for(i=1;i<=n;i++){
 		cin>>a[i]>>x;
 		add(x,i);add(i,x); 
 	}
 	for(i=1;i<=n;i++){
 		if(vis[i]) continue;
 		find(i,-1);
 		dp(rt1,-1); t1=f[rt1][0];
 		
 		dp(rt2,-1); t2=f[rt2][0];
 		ans+=max(t1,t2);
 	}
 	cout<<ans;
 }

 

posted on 2023-03-06 20:13  towboat  阅读(17)  评论(0)    收藏  举报