题解

cookiebus 2022-04-10 10:33:06 2024-01-30 20:25:22 9 返回题目

f[u][j] 表示以 u 为根的子树如果删掉j条边且跟u断开连接的连通块 >= 0 的情况下,跟u相连的部分的最大值是多少。

然后做一个树上背包即可。树上背包时间复杂度O(n^2)

最大答案就是求一个最大的 ans, 满足 f[1][ans] >= 0

参考代码

#include <bits/stdc++.h>
#define int long long


using namespace std;
const int inf = INT_MAX / 3;
const int N = 2000 + 10;
vector<int> g[N];
int n, m, sz[N], f[N][N * 2], fa, a[N], dp[N];
void dfs(int u) {
    sz[u] = 1;
    f[u][0] = a[u];
    for (int v : g[u]) {
        dfs(v);
        for (int j = sz[u] + sz[v] - 1; j >= 0; --j) dp[j] = -inf;
        for (int j = sz[u] - 1; j >= 0; --j)
            if (f[u][j] != -inf)
                for (int k = min(sz[u] + sz[v] - 1 - j, sz[v] - 1); k >= 0; --k)
                    if (f[v][k] != -inf) {
                        if (f[v][k] >= 0) {
                            dp[j + k + 1] = max(dp[j + k + 1], f[u][j]);
                        }
                        dp[j + k] = max(dp[j + k], f[u][j] + f[v][k]);
                    }
        for (int j = sz[u] + sz[v] - 1; j >= 0; --j) f[u][j] = dp[j];
        sz[u] += sz[v];
    }
}
signed main() {
    cin >> n;
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= n; ++j) f[i][j] = -inf;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    for (int i = 2; i <= n; ++i) {
        int fa;
        cin >> fa;
        g[fa].push_back(i);
    }
    dfs(1);
    for (int i = n - 1; i >= 0; --i)
        if (f[1][i] >= 0) {
            cout << i << endl;
            return 0;
        }
    cout << -1 << endl;
    return 0;
}
{{ vote && vote.total.up }}