Codeforces Round #660 (Div. 2) D. Captain Flint and Treasure ###K ### //K
题目链接:https://codeforces.ml/contest/1388/problem/D
题意:一种操作为 选一个下标 使得ans+=a[i] 且 把a[i]+到a[b[i]]中 要求每个下标都进行一种这样的操作,问怎么样的操作顺序才能使得ans最大
思路:要使得ans最大,那么肯定是a[i]为正数的都尽量早的累加,为负数的都尽量晚的累加,那么现在只需要考虑如何遍历就行了,题目已经说明是
有向无环图,那么首先想到的就应该是拓扑排序, 拓扑排序后, 正数应该从序号小的累加到序号大的, 这样能最大贡献, 负数应该从序号大的累加到序号小的,才能使得负数贡献小
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =2e5+10; 6 const int mod=1e9+7; 7 ll a[maxn]; 8 int b[maxn]; 9 int ru[maxn]; 10 int num[maxn]; 11 12 13 bool cmp(pair<int,int>a,pair<int,int>b) 14 { 15 return a.first>b.first; 16 } 17 18 int main() 19 { 20 ios::sync_with_stdio(false); 21 cin.tie(0); 22 int n; 23 cin>>n; 24 for(int i=1;i<=n;i++) 25 { 26 cin>>a[i]; 27 } 28 for(int i=1;i<=n;i++) 29 { 30 cin>>b[i]; 31 if(b[i]==-1) 32 b[i]=0; 33 ru[b[i]]++; 34 } 35 queue<int>q; 36 for(int i=1;i<=n;i++) 37 { 38 if(ru[i]==0) 39 q.push(i); 40 } 41 ll ans=0; 42 vector<int>cnt; 43 int tot=0; 44 while(!q.empty()) 45 { 46 int u=q.front(); 47 num[u]=++tot; 48 int v=b[u]; 49 q.pop(); 50 if(a[u]>=0) 51 { 52 a[v]+=a[u]; 53 ans+=a[u]; 54 cnt.pb(u); 55 } 56 ru[v]--; 57 if(ru[v]==0&&v!=0) 58 q.push(v); 59 } 60 vector<pair<int,int>>temp; 61 for(int i=1;i<=n;i++) 62 { 63 if(a[i]<0) 64 { 65 temp.pb({num[i],i}); 66 } 67 } 68 sort(temp.begin(),temp.end(),cmp); 69 for(auto &v:temp) 70 { 71 ans+=a[v.second]; 72 cnt.pb(v.second); 73 } 74 75 cout<<ans<<'\n'; 76 for(auto &v:cnt) 77 cout<<v<<" "; 78 79 80 81 82 83 }

浙公网安备 33010602011771号