D. Captain Flint and Treasure(DFS&贪心)

D. Captain Flint and Treasure(DFS&贪心)

思路: d f s + dfs+ 贪心。

考虑:将 b [ i ] i b[i]\rightarrow i 作为一条有向边,建图。

先从 b [ i ] = = 1 b[i]==-1 的点开始 d f s dfs ,因为它不会再对其他点产生贡献,只有其他点会对它产生贡献,因为 d f s dfs 的特性,我们会优先将 a [ i ] 0 a[i]\geq0 的叶子节点加入一个数组 c c ,这样对于其他结点的收益是最大的,对于 a [ i ] < 0 a[i]<0 的结点我们则加入另一个数组 d d ,这样建立两个数组是因为,对于 a [ i ] < 0 a[i]<0 的结点,深度越大的结点,祖先越多,负面影响越大,所以输出答案的时候要将他们倒序输出。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define reg register
#define pb push_back
ll a[N],ans;
int n,m,b[N];
vector<int>c,d,e[N]; 
void dfs(int u,int fa){
	for(auto v:e[u]){
		if(v==fa) continue;
		dfs(v,u);
		if(a[v]>=0) a[u]+=a[v];
	}
	a[u]>=0?c.pb(u):d.pb(u);
	ans+=a[u];
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
		if(~b[i]) e[b[i]].pb(i);
	}
	for(int i=1;i<=n;i++)
		if(b[i]==-1) dfs(i,0);
	printf("%lld\n",ans);
	for(int i:c) printf("%d ",i);
	for(int i=d.size()-1;~i;i--) printf("%d ",d[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107707181
今日推荐