30pts,悬赏一关注求hack数据
查看原帖
30pts,悬赏一关注求hack数据
462050
Misakura_Rin楼主2024/10/11 22:47

rt

#include<iostream>
#include<cstdio>
#define MAXN int(1e6+5)
#define ll long long
using namespace std;
int n;
ll atk[MAXN];
int hate[MAXN][2],sum=0;
bool usd[MAXN];
int head[MAXN],tot=0;
struct node{
	int u,v,nxt;
}e[MAXN<<1];
inline void addedge(int u,int v){
	e[++tot]={u,v,head[u]},head[u]=tot;
}
bool root[MAXN];
ll satk[MAXN];//每个连通块的总战力
ll f[2][MAXN];//选 Or 不选的最大战力
void dp(int u){
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].v;
		dp(v);
		f[0][u]+=f[1][v];
		f[1][u]+=max(f[0][v],f[1][v]);
	}
}
ll ans=0;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int v;
		scanf("%lld%d",atk+i,&v);
		if(usd[i]&&usd[v]){
			//成环
			hate[++sum][0]=i;
			hate[sum][1]=v;
		}else{
			usd[i]=1,usd[v]=1;
			addedge(v,i);
			root[i]=1;
		}
	}
	for(int i=1;i<=n;i++)f[0][i]=atk[i];
	for(int i=1;i<=sum;i++){
		f[0][hate[i][0]]=0;//先ban掉一边
	}
	for(int i=1;i<=n;i++){
		if(!root[i]){
			dp(i);
			satk[i]=max(f[0][i],f[1][i]);
		}
	}
	for(int i=1;i<=n;i++)f[0][i]=atk[i],f[1][i]=0;
	for(int i=1;i<=sum;i++){
		f[0][hate[i][1]]=0;
	}
	for(int i=1;i<=n;i++){
		if(!root[i]){
			dp(i);
			satk[i]=max(satk[i],max(f[0][i],f[1][i]));
		}
	}
	for(int i=1;i<=n;i++){
		ans+=satk[i];
	}
	printf("%lld",ans);
	return 0;
}
2024/10/11 22:47
加载中...