題意node
給長度爲\(n\)的序列\(a[n]\)和\(b[n]\),初始時\(ans=0\),有如下操做:ios
問每一個元素操做一次後,\(ans\)最大爲多少,並輸出操做序列c++
分析spa
對於一個數,若是他有前驅的話,能夠考慮對於其某些前驅進行操做後再操做該數,那麼畫一個前驅圖能夠發現,這是一個拓撲排序的題,操做到某個節點時code
那麼拓撲排序的時候維護一個隊列和一個棧,對於值大於\(0\)的節點,將其放入隊列中,而後將其值加入後續節點,不然將其放入棧中(由於若連續兩個節點值都小於\(0\),那麼應先操做後續節點),最後輸出便可排序
#pragma GCC optimize(3, "Ofast", "inline") #include <bits/stdc++.h> #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define ll long long #define int ll #define ls st<<1 #define rs st<<1|1 #define pii pair<int,int> #define rep(z, x, y) for(int z=x;z<=y;++z) #define repd(z, x, y) for(int z=x;z>=y;--z) #define com bool operator<(const node &b)const using namespace std; mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count()); const int maxn = (ll) 3e5 + 5; const int mod = 998244353; const int inf = 0x3f3f3f3f; int T = 1; int a[maxn], b[maxn]; vector<int> v[maxn]; int in[maxn]; void solve() { int n; cin >> n; rep(i, 1, n)cin >> a[i]; rep(i, 1, n) { cin >> b[i]; if (b[i] != -1) { v[i].push_back(b[i]); ++in[b[i]]; } } int ans = 0; queue<int> q; rep(i, 1, n) { if (in[i] == 0) { q.push(i); } } vector<int> tmp; stack<int> last; while (!q.empty()) { int now = q.front(); if (a[now] > 0) tmp.push_back(now); else last.push(now); ans += a[now]; q.pop(); for (auto &to:v[now]) { if (a[now] > 0) a[to] += a[now]; --in[to]; if (in[to] == 0) { q.push(to); } } } cout << ans << '\n'; for (auto &to:tmp)cout << to << ' '; while (!last.empty()) { cout << last.top() << ' '; last.pop(); } } signed main() { start; while (T--) solve(); return 0; }