P1352 没有上司的舞会 / 树形dp
某大学有 \(n\) 个职员,编号为 \(1\dots n\)。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。
现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 \(r_i\),但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。
所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
解法
我们设 \(dp_{(i,j)}\) 表示当前选不选择第 \(i\) 个人所能获得的最大快乐值,其中 \(j\in [0,1]\)。随后进行递归转移即可。
#include <iostream>
#include <vector>
using namespace std;
const int kMaxN = 6e3 + 5;
int a[kMaxN], d[kMaxN], dp[kMaxN][2], n, r;
vector<int> e[kMaxN];
void dfs(int x) {
for (int i : e[x]) {
dfs(i); // 递归提前处理完子树
dp[x][0] += max(dp[i][0], dp[i][1]); // 不选当前上司
dp[x][1] += dp[i][0]; // 选择当前上司
}
dp[x][1] += a[x]; // 当前上司一起跳舞
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1, l, k; i < n; i++) {
cin >> l >> k;
e[k].push_back(l); //存边
d[l]++; // 入度加一
}
for (int i = 1; i <= n; i++) {
if (!d[i]) { // 找根结点
r = i;
break;
}
}
dfs(r);
cout << max(dp[r][0], dp[r][1]) << '\n';
return 0;
}

浙公网安备 33010602011771号