D. Captain Flint and Treasure(DFS&贪心)
思路: 贪心。
考虑:将 作为一条有向边,建图。
先从 的点开始 ,因为它不会再对其他点产生贡献,只有其他点会对它产生贡献,因为 的特性,我们会优先将 的叶子节点加入一个数组 ,这样对于其他结点的收益是最大的,对于 的结点我们则加入另一个数组 ,这样建立两个数组是因为,对于 的结点,深度越大的结点,祖先越多,负面影响越大,所以输出答案的时候要将他们倒序输出。
#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;
}