CF1388D Captain Flint and Treasure

可以发现题目给出的是一个森林,对于每一棵树进行一次记忆化,记录走完当前节点子树后,当前节点的最大累计值。(第一问)
对于第二问,我们每次先遍历能对当前节点做出贡献的子节点(即权值为正),然后对于不能对当前节点做出贡献的子节点放在后面遍历(即无关紧要了)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,ans,tot;
int a[N],b[N],sum[N],du[N];
int cnt,head[N];
struct edge{
    
    int next,to;}e[N];

inline void add(int u,int v)
{
    
    	
	cnt++;
	e[cnt].next=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}

void dfs(int u)
{
    
    
	for (register int i=head[u]; i; i=e[i].next)
	{
    
    
		dfs(e[i].to);
		if (sum[e[i].to]>0) sum[u]+=sum[e[i].to];
	}
}	

void dfs2(int u)
{
    
    
	for (register int i=head[u]; i; i=e[i].next) if (sum[e[i].to]>=0) dfs2(e[i].to);
	printf("%lld ",u);
	for (register int i=head[u]; i; i=e[i].next) if (sum[e[i].to]<0) dfs2(e[i].to);
}

signed main(){
    
    
	scanf("%lld",&n);
	for (register int i=1; i<=n; ++i) scanf("%lld",&a[i]);
	for (register int i=1; i<=n; ++i)
	{
    
    
		scanf("%lld",&b[i]);
		if (~b[i]) add(b[i],i),du[i]++;	
	}
	for (register int i=1; i<=n; ++i) sum[i]=a[i];
	for (register int i=1; i<=n; ++i) if (!du[i]) dfs(i);
//	for (register int i=1; i<=n; ++i) printf("%lld ",sum[i]); puts("");
	for (register int i=1; i<=n; ++i) ans+=sum[i];
	printf("%lld\n",ans);
	for (register int i=1; i<=n; ++i) if (!du[i]) dfs2(i);
return 0;
}

猜你喜欢

转载自blog.csdn.net/Dove_xyh/article/details/108288160
今日推荐