20pts:先找出每棵树的环,在对环上节点处理(有思路一样的吗,求调qwq
查看原帖
20pts:先找出每棵树的环,在对环上节点处理(有思路一样的吗,求调qwq
556740
hzx360楼主2022/8/8 13:19
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+100;
int n,p[N];
long long dp[N][2];
int head[N],to[N],ne[N],tot;
void add(int x,int y){
	ne[++tot]=head[x];
	to[tot]=y;
	head[x]=tot;
}
vector<int>g;
bool vis[N],flag[N],yes;
int st[N],in[N],cnt;
void find_circle(int u,int fa){
	flag[u]=1;
	vis[u]=1,g.push_back(u);
	for(int i=head[u];i;i=ne[i]){
		if(yes)return;
		int v=to[i];
		if(v==fa)continue;
		if(vis[v]){
			int o;
			do{
				o=g.back(),g.pop_back();
				in[o]=1;
				st[++cnt]=o;
			}while(o!=v);
			yes=1;
			return;
		}
		find_circle(v,u);
	}
	vis[u]=0,g.pop_back();
}
void dfs(int u,int fa){
	flag[u]=1;
	dp[u][1]=p[u];
	for(int i=head[u];i;i=ne[i]){
		int v=to[i];
		if(v==fa)continue;
		dfs(v,u);
		dp[u][1]+=dp[v][0];
		dp[u][0]+=max(dp[v][1],dp[v][0]);
	}
}
long long f[N][2];
long long get(int o){
	long long ans;
	yes=0;
	cnt=0,g.clear();
	find_circle(o,0);
	for(int k=1;k<=cnt;k++){
		int u=st[k];
		for(int i=head[u];i;i=ne[i]){
			int v=to[i];
			dp[u][1]=p[u];
			if(in[v])continue;
			dfs(v,u);
			dp[u][1]+=dp[v][0];
			dp[u][0]+=max(dp[v][0],dp[v][1]);
		}
	}
	if(cnt==0) return max(p[o],p[to[head[o]]]);
	f[st[2]][0]=dp[st[2]][0]+dp[st[1]][0],f[st[2]][1]=dp[st[2]][1]+dp[st[1]][0];
	for(int i=3;i<=cnt;i++){
		f[st[i]][0]=max(f[st[i-1]][0],f[st[i-1]][1])+dp[st[i]][0];
		f[st[i]][1]=f[st[i-1]][0]+dp[st[i]][1];
	}
	ans=max(f[st[cnt]][0],f[st[cnt]][1]);
	if(dp[st[1]][1]+dp[st[2]][0]<=f[st[2]][0])return ans;
	f[st[2]][0]=dp[st[1]][1]+dp[st[2]][0];
	for(int i=3;i<=cnt;i++){
		f[st[i]][0]=max(f[st[i-1]][0],f[st[i-1]][1])+dp[st[i]][0];
		f[st[i]][1]=f[st[i-1]][0]+dp[st[i]][1];
	}
	ans=max(ans,f[st[cnt]][0]);
	return ans;
}
int main(){
	cin>>n;
	for(int k=1;k<=n;k++){
		int x;
		scanf("%d%d",&p[k],&x);
		add(k,x),add(x,k);
	}
	long long ans=0;
	for(int k=1;k<=n;k++)
		if(!flag[k]) ans+=get(k);
	cout<<ans;
}
2022/8/8 13:19
加载中...