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

浙公网安备 33010602011771号