17 ACwing 285 没有上司的舞会 题解

没有上司的舞会

题面

Ural 大学有 N 名职员,编号为 1∼N。

他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。

每个职员有一个快乐指数,用整数 Hi 给出,其中 1≤i≤N。

现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。

在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。

题解

树形dp板题,设 \(f(x,0/1)\) 表示 \(x\) 这个点选/不选的最大价值

树形dp的计算过程一般是自顶向下的递归,还有自底向上的拓扑排序

这里用从上向下即可,转移

\[\begin {align} &f(x,0) = \sum_{y \in son_x} max \{f(y,0), f(y, 1)\} \\ &f(x,1) = \sum_{y \in son_x} f(y, 0) \end {align} \]

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 6e3 + 10;

int n;
int H[N], f[N][2];
int h[N], ver[N], ne[N], tot;
bool fa[N];

void add (int x, int y) {
    ver[++tot] = y;
    ne[tot] = h[x];
    h[x] = tot;
}

void dfs (int x, int fa) {
    f[x][0] = 0;
    f[x][1] = H[x];
    for (int i = h[x]; i; i = ne[i]) {
        int y = ver[i];
        dfs (y, x);
        f[x][0] += max (f[y][0], f[y][1]);
        f[x][1] += f[y][0];
    }
}

int main () {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> H[i];
    }

    for (int i = 1; i < n; i ++) {
        int x, y;
        cin >> x >> y;
        add (y, x);
        fa[x] = 1;
    }
    int root = 0;
    for (int i = 1; i <= n; i ++) {
        if (!fa[i]) root = i;
    }
    dfs (root, 0);
    cout << max (f[root][0], f[root][1]) << endl;
    return 0;
}
posted @ 2025-10-05 18:01  michaele  阅读(18)  评论(0)    收藏  举报