Codeforces 1388D Captain Flint and Treasure(贡献+拓扑序)
题意:给出a【】和b【】长度为n,一次操作:val+=a[i], a[b[i]]+=a[i] (b[i]!=-1);对每个i(1-n)都执行一次操作,求最大的val并输出操作的次序。
题解:考虑a【i】对答案的贡献,如果a【i】大于0的话,应使得a【i】对答案的贡献次数尽可能多,即按照拓扑序往后即可;或者a【i】小于等于0,应对答案的贡献次数尽可能小,反向的拓扑序列即可。
#include <bits/stdc++.h> #define IO_read ios::sync_with_stdio(false);cin.tie(0) #define fre freopen("C:\\in.txt", "r", stdin) #define _for(i,a,b) for(int i=a; i< b; i++) #define _rep(i,a,b) for(int i=a; i<=b; i++) #define inf 0x3f3f3f3f #define lowbit(a) ((a)&-(a)) using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0'; if(op) x=-x; } const int maxn=2e5+5; int n, in[maxn]; ll a[maxn], b[maxn]; vector<int> v1, v2, g[maxn]; ll ans; void topo() { queue<int> que; _rep(i, 1, n) if(!in[i]) que.push(i); while(!que.empty()){ int u=que.front(); que.pop(); ans+=a[u]; if(a[u]>0) v1.push_back(u); else v2.push_back(u); for(auto &v: g[u]){ if(a[u]>0)a[v]+=a[u]; in[v]--; if(!in[v]) que.push(v); } } } int main() { read(n); _rep(i, 1, n) read(a[i]); _rep(i, 1, n) read(b[i]); _rep(i, 1, n) if(b[i]!=-1) g[i].push_back(b[i]), in[b[i]]++; topo(); printf("%lld\n", ans); for(auto &v: v1) printf("%d ",v); reverse(v2.begin(), v2.end()); for(auto &v: v2) printf("%d ",v); return 0; }