树上求和
题目链接:ybt高效进阶5-4-1
题目大意
给你一棵树,要你选一些点,使得选的点之间没有父子关系,而且点权和最大。
思路
明显的树形DP。
设
f
i
,
0
/
1
f_{i,0/1}
fi,0/1 为处理好
i
i
i 的子树,
i
i
i 这个点不选或选的最大点权和。
然后枚举儿子从小向上转移一下就可以了。
代码
#include<cstdio>
#include<iostream>
using namespace std;
struct node {
int to, nxt;
}e[6001];
int n, a[6001], x, y, rt;
int le[6001], KK, fa[6001];
int f[6001][2];
void add(int x, int y) {
e[++KK] = (node){y, le[x]}; le[x] = KK;
}
void dfs(int now, int father) {
f[now][0] = 0; f[now][1] = a[now];
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father) {
dfs(e[i].to, now);
f[now][0] += max(max(f[e[i].to][1], f[e[i].to][0]), 0);
f[now][1] += max(f[e[i].to][0], 0);
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i < n; i++) {
scanf("%d %d", &x, &y);
add(y, x); fa[x] = y;
}
for (int i = 1; i <= n; i++)
if (!fa[i]) {
rt = i; break;
}
dfs(rt, 0);
printf("%d", max(f[rt][0], f[rt][1]));
return 0;
}