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;
}