50pts求助,请问该新做法是否可行
查看原帖
50pts求助,请问该新做法是否可行
531650
emmc楼主2024/8/16 17:10

P2607 [ZJOI2008] 骑士 我在做这道题的时候想到了与题解不同一种解法

在遇到环的时候多开一个dp2数组,单独处理带环的子树(不选择与根节点冲突的),在出环时把dp2合并进原来的dp数组,但是没过。TAT

请问这种做法是否可行,如果不可行,有没有巨佬可以帮我解释一下,谢谢!

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1*1e6+100;
vector <int>e[N];
int dp[N][2];
int dp2[N][2];
int h[N];
int vis[N];
int v[N];
int n;
void pre(int p){
	vis[p]=1;
	for(int k:e[p]){
		if(vis[k]){
			h[p]=1;
		}
		else pre(k),h[p]+=h[k];
	}
}
int dfs(int p,int fa){
	dp[p][1]=dp2[p][1]=v[p];
	vis[p]=1;
	int ret=0;
	if(!h[fa] and h[p]) ret=2;
	for(int k:e[p]){
		if(vis[k]){
			ret=1;
		}
		else{
			if(dfs(k,p)){
				dp2[p][0]+=dp[k][0];
				dp2[p][1]+=dp[k][0];
			}
			else if(h[p] and ret!=2){
				dp2[p][0]+=max(dp2[k][1],dp2[k][0]);
				dp2[p][1]+=dp2[k][0];
			}
			if(ret==2){
				dp[p][0]+=max(dp[k][1],dp[k][0]);
				dp[p][1]+=dp2[k][0];
			}
			else{
				dp[p][0]+=max(dp[k][1],dp[k][0]);
				dp[p][1]+=dp[k][0];
			}
		}
	}
	if(!h[p]){
		dp2[p][0]=dp[p][0];
		dp2[p][1]=dp[p][1];
	}
	return ret;
}
int cd[N];
int rd[N];
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int t1,t2;
		cin>>t1>>t2;
		v[i]=t1;
		e[t2].push_back(i);
		cd[t2]++;
		rd[i]++;	
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]) pre(i);	
	}
	int ans=0;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++){
		if(h[i]==1 and !vis[i]){
			dfs(i,0);
			ans+=max(dp[i][1],dp[i][0]);
		}
	}
	cout<<ans<<endl;
}
2024/8/16 17:10
加载中...