树形DP: 没有上司的舞会
c++
没有上司的舞会
/*
* 没有上司的舞会
* 题目描述:
* Ural 大学有 N 名职员,编号为 1∼N。
* 他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。
* 每个职员有一个快乐指数,用整数 Hi 给出,其中 1≤i≤N。
* 现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。
* 在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。
* 数组含义:
* f[i][1] 表示用了, f[i][0] 表示没有用
*
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
using namespace std;
const int N = 6010;
int n;
int h[N], ne[N], e[N], idx;
int w[N];
int f[N][2];
bool st[N];
void add(int x, int y) {
e[idx] = y, ne[idx] = h[x], h[x] = idx ++;
}
void dfs(int x) {
int y;
f[x][0] = 0;
f[x][1] = w[x];
for (int i = h[x]; ~i; i = ne[i]) {
y = e[i];
dfs(y);
f[x][0] += max(f[y][0], f[y][1]);
f[x][1] += f[y][0];
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
scanf("%d", &w[i]);
}
idx = 1;
memset(h, -1, sizeof h);
memset(ne, -1, sizeof ne);
memset(st, false, sizeof st);
for (int i = 1; i < n; i ++ ) {
static int l, k;
scanf("%d%d", &l, &k); // k is boss
add(k, l);
st[l] = true;
}
int root = -1;
for (int i = 1; i <= n; i ++ ) {
if (st[i] == false) {
root = i;
break; // 按道理说也是只有一个
}
}
memset(f, 0, sizeof f);
// printf("root=%d\n", root);
dfs(root);
printf("%d\n", max(f[root][0], f[root][1]));
return 0;
}