原题链接
对于这个问题,我们只需要考虑a[i]>=0的叠加到a[b[i]],因为a[i]加到a[b[i]]上,我们可以发现有向边考虑拓扑排序,对于a[i]大于等于0的直接叠加到a[b[i]],然后把a[i]<0的点直接存入即可
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
using namespace std;
const int maxn = 2e5 + 5;
vector<int>g[maxn],v;
ll a[maxn],ans;
int in[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
}
for(int i = 1; i <= n; i++){
int x;
scanf("%d",&x);
if(x != -1){
g[i].push_back(x);
in[x]++;
}
}
ans = 0;
queue<int>q;
for(int i = 1; i <= n; i++){
if(in[i] == 0)q.push(i);
}
stack<int>s;
while(!q.empty()){
int x = q.front();
q.pop();
if(a[x] >= 0)ans += a[x],v.push_back(x);
else s.push(x);
for(int i = 0; i < g[x].size(); i++){
int j = g[x][i];
if(a[x] >= 0)a[j] += a[x];
--in[j];
if(!in[j])q.push(j);
}
}
while(!s.empty()){
int x = s.top();
s.pop();
ans += a[x];
v.push_back(x);
}
printf("%lld\n",ans);
for(int i = 0; i < v.size(); i++){
if(i == v.size() - 1)printf("%d\n",v[i]);
else printf("%d ",v[i]);
}
}