Anniversary party POJ - 2342 树形dp

发布时间 2023-09-19 18:46:05作者: HelloHeBin

题意:某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

分析:

  1. 状态
    f[u][0] 表示以u为根节点,且不选u的最大快乐指数。
    f[u][1] 表示以u为根节点,且选u的最大快乐指数。

  2. 转移
    如果不选u,对于u的子节点v可以选或不选:f[u][0] += max(f[v][0], f[v][1]);
    如果选u,对于u的子节点v只能不选:f[u][0] += f[v][0];

  3. 目标
    ans = max(f[rt][0], f[rt][1])

点击查看代码
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10, INF = 0x3f3f3f3f;
int n, a[N], f[N][2];
struct T {
    int v, w, nx;
} g[N];
int h[N], idx;
bool st[N];
void add(int u, int v, int w) {
    g[++idx] = {v, w, h[u]}, h[u] = idx;
}
void dfs(int u) {
    f[u][0] = 0, f[u][1] = a[u];
    for (int i = h[u]; i; i = g[i].nx) {
        int v = g[i].v;
        dfs(v);
        f[u][0] += max(f[v][0], f[v][1]);
        f[u][1] += f[v][0];
    }
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1, u, v; i <= n; i++) {
        cin >> u >> v, st[u] = 1;
        add(v, u, 1);
    }
    int rt = 1;
    while (st[rt])
        rt++;
    dfs(rt);
    cout << max(f[rt][0], f[rt][1]);
    return 0;
}