CodeForces 1388D Captain Flint and Treasure
阅读原文时间:2023年09月03日阅读:3

题意

给长度为\(n\)的序列\(a[n]\)和\(b[n]\),初始时\(ans=0\),有以下操作:

  • \(ans=ans+a[i]\)
  • 如果\(b[i]\neq-1\),则\(a[b[i]]=a[b[i]]+a[i]\)

问每个元素操作一次后,\(ans\)最大为多少,并输出操作序列

分析

对于一个数,如果他有前驱的话,可以考虑对于其某些前驱进行操作后再操作该数,那么画一个前驱图可以发现,这是一个拓扑排序的题,操作到某个节点时

  • 如果该节点的值大于\(0\),说明将其操作到后续节点一定是更优的
  • 否则,这个节点一定要晚于其后续节点操作,否则会将该节点的值再贡献一次

那么拓扑排序的时候维护一个队列和一个栈,对于值大于\(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;
}