树形DP
状态表示:
树形DP的状态集合有两个f[u, 0]和f[u, 1],分别表示所有从以u为根的子树中选择,且不选u这个点的方案,和选这个点的方案。
首先对于f[u, 0],因为它没有选择u这个点,因此子节点自由选择,可以由f[j , 0]和f[j, 1]中转移过来,取两者最大值即可。
f[u][0] = max(f[j][1], f[j][0]);
对于f[u, 1],由于选择了u节点,因此子节点必不能选,它等同于f[j, 0]和happy(u)
f[u][1] = f[j][0] + happy[u];
还有一点,即我们需要算完子节点,才能知道上司的情况,因此我们需要用递归的形式来做,搜索的方式可以选择dfs,同时可以给相应的f[u] [x]赋一个开心值。
#include <bits/stdc++.h>
using namespace std;
const int N = 6010;
int n;
int h[N], e[N], ne[N], idx;
int happy[N];
int f[N][2];
bool has_fa[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs(int u)
{
f[u][1] = happy[u];
for (int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
dfs(j);
f[u][1] += f[j][0];
f[u][0] += max(f[j][0], f[j][1]);
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> happy[i];
memset(h, -1, sizeof h);
for (int i = 0; i < n - 1; i ++ ){
int a, b;
cin >> a >> b;
add(b, a);
has_fa[a] = true;
}
int root = 1;
while (has_fa[root]) root ++;
dfs(root);
cout << max(f[root][0], f[root][1]) << endl;
return 0;
}