题目链接:POJ 2342
题意:在一个公司里,每个成员都有各自的rating,要参加一次年会,规定 有直接上下级关系的任意两人不能同时参加,并且要使参加年会成员的rating值最大;
题解:关于树形dp—树形dp总结
而对于这题,对于么个成员都有去不去两种可能,用dp[i][0]表示他不去的最大rating值,dp[i][1]表示去的最大rating
因此:
dp[x][0] += max(dp[i][0], dp[i][1]);
dp[x][1] += dp[i][0];//i为x的直接下级
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define debug 0
#define M(a, b) memset(a, b, sizeof(a))
const int maxn = 6000 + 5;
int father[maxn], a[maxn], n, dp[maxn][2], vis[maxn];
void Dp(int x) {
vis[x] = 1;
for (int i = 1; i <= n; i++) {
if (vis[i]) //这题用vis[]降低遍历,额 其实并没有什么卵用
continue;
if (father[i] == x) {
Dp(i); //递归调用直接下级
dp[x][0] += max(dp[i][0], dp[i][1]);
dp[x][1] += dp[i][0];
}
}
}
int main() {
#if debug
freopen("in.txt", "r", stdin);
#endif //debug
int x, y, root;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
dp[i][0] = 0;
dp[i][1] = a[i];
}
M(father, 0);
M(vis, 0);
while (~scanf("%d%d", &x, &y), x + y) {
father[x] = y; //用数组模拟树,记录上下级关系
root = y; //root 记录当前的上级
}
while (father[root])
root = father[root]; //寻找根节点(目测是boss)
Dp(root); //递归
printf("%d\n", max(dp[root][0], dp[root][1]));
return 0;
}