Captain Flint and Treasure
一种操作为 选一个下标 使得ans+=a[i] 且 把a[i]+到a[b[i]]中 要求每个下标都进行一种这样的操作,问怎么样的操作顺序才能使得ans最大
思路:要使得ans最大,那么肯定是a[i]为正数的都尽量早的累加,为负数的都尽量晚的累加,那么现在只需要考虑如何遍历就行了,题目已经说明是
有向无环图,那么首先想到的就应该是拓扑排序,从入度为0开始,这样才能最大限度的累加
遍历完之后, 再从出度为0的先进行操作,这样剩下的负数就不会累加到其他数上
Input
3 1 2 3 2 3 -1
Output
10 1 2 3
Input
2 -1 100 2 -1
Output
99 2 1
Input
10 -10 -1 2 2 5 -2 -3 -4 2 -6 -1 -1 2 2 -1 5 5 7 7 9
Output
-9 3 5 6 1 9 4 10 7 8 2
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back const int maxn=2e5+10; const int mod=1e9+7; ll a[maxn]; ll b[maxn]; int ru[maxn]; int chu[maxn]; vector<int>E[maxn]; vector<int>G[maxn]; int vis[maxn]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; ll sum=0; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=1;i<=n;i++) { cin>>b[i]; } vector<int>ans; for(int i=1;i<=n;i++) { if(b[i]==-1) continue; ru[b[i]]++; chu[i]++; E[i].pb(b[i]); G[b[i]].pb(i); } queue<int>q; for(int i=1;i<=n;i++) { if(ru[i]==0) { q.push(i); } } while(!q.empty()) { int u=q.front(); q.pop(); for(auto &v:E[u]) { ru[v]--; if(a[u]>=0) { a[v]+=a[u]; sum+=a[u]; ans.pb(u); vis[u]=1; } if(ru[v]==0) { q.push(v); } } } queue<int>qh; for(int i=1;i<=n;i++) { if(chu[i]==0&&vis[i]==0) { qh.push(i); } } while(!qh.empty()) { int u=qh.front(); qh.pop(); if(vis[u]==0) { sum+=a[u]; ans.pb(u); } for(auto &v:G[u]) { chu[v]--; if(chu[v]==0) qh.push(v); } } cout<<sum<<'\n'; for(auto &v:ans) { cout<<v<<" "; } }