骑士(基环树板子)

题目链接:https://www.luogu.com.cn/problem/P2607

题意:

思路:

图为外向树,(n个节点,n个边)
对于每一个连通块,先找环(每个连通块都有一个环)然后断环成树,跑树形dp板子

vector<int>e[maxn];
int vis[maxn],w[maxn];
ll f[maxn][2];
int r1,r2;
void find(int u,int rt){//找环 
	vis[u]=1;
	for(int v:e[u]){
		if(v==rt){
			r1=u,r2=v;return;
		}//找到环且遍历完连通块 
		if(vis[v])continue;
		find(v,rt);
	}
}

ll dfs(int u,int rt){
	f[u][0]=0;f[u][1]=w[u];
	for(int v:e[u]){
		if(v==rt)continue;//断环操作,防止无限循环 
		dfs(v,rt);
		f[u][0]+=max(f[v][0],f[v][1]);
		f[u][1]+=f[v][0];
	}
	return f[u][0];//不选u 
}

void solve(){
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		int v,u;cin>>v>>u;
		e[u].pb(i);w[i]=v;
		//让讨厌的骑士作为该骑士的父亲 
	}
	int sum=0;
	for(int i=1;i<=n;i++){
		if(!vis[i]){//对于每一个连通块 
			r1=r2=0;
			find(i,i);
			if(r1){
				ll res1=dfs(r1,r1);
				ll res2=dfs(r2,r2);
				sum+=max(res1,res2);
			}
		}
	}
	cout<<sum<<endl;
}
posted @ 2025-04-01 21:29  Marinaco  阅读(16)  评论(0)    收藏  举报
//雪花飘落效果