51Nod 2605 没有上司的舞会

题目链接:51Nod 2605 没有上司的舞会

题目大意:

题解:
树形\(dp\)很经典的一道题,各职员的上下级关系可以构成一棵树。
\(dp[i][1/0]\)表示编号为\(i\)的职员参加或不参加聚会时,以他为根的子树所能获得的最大快乐指数。
当某职员参加聚会时,他的下级只能不参加;当他不参加聚会时,他的下级可以选择参加或不参加。
状态转移方程:

\[dp[fa][0] = \sum max\{dp[son][0], dp[son][1]\} \]

\[dp[fa][1] = r[fa] + \sum dp[son][0] \]

答案为:\(max\{dp[1][0], dp[1][1]\}\)

#include <cstring>
#include <iostream>
using namespace std;

int dp[100010][2], n, r[100010], cnt, head[100010];
struct Edge {
    int v, next;
} edge[200010];

void addEdge(int u, int v) {
    edge[++cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

void dfs(int now, int pre) {
    dp[now][0] = 0;
    dp[now][1] = r[now];
    for (int i = head[now]; i; i = edge[i].next) {
        if (edge[i].v == pre) {
            continue;
        }
        dfs(edge[i].v, now);
        dp[now][0] += max(dp[edge[i].v][0], dp[edge[i].v][1]);
        dp[now][1] += dp[edge[i].v][0];
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> r[i];
    }
    for (int i = 1, u, v; i < n; ++i) {
        cin >> u >> v;
        addEdge(u, v);
        addEdge(v, u);
    }
    dfs(1, 0);
    cout << max(dp[1][0], dp[1][1]);
    return 0;
}
posted @ 2021-07-26 02:52  ZZHHOOUU  阅读(90)  评论(0编辑  收藏  举报