AcWing 285. 没有上司的舞会
原题链接
简单
作者:
congee
,
2021-03-18 12:47:42
,
所有人可见
,
阅读 278
//树形DP
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 6010;//N最大值为6000
int n;
int h[N], e[N], ne[N], idx;
int happy[N];//记录每个节点的快乐值
int f[N][2];//一维即是每个结点,二维0表示不选这个节点,1表示选这个节点
bool has_fa[N];//has_fa[a]用来记录a是否有父亲节点,有则为true
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; i = ne[i])// -1取反为0;遍历节点u的子节点
{
int j = e[i];
dfs(j);//dfs节点u的一个子节点j
//运行至此时f[j][0]与f[j][1]都已经在上面的dfs(j)中计算完成
f[u][1] += f[j][0];//选节点u则其子节点j就不能选,直接加上不选节点j的选法f[j][0]即可
f[u][0] += max(f[j][0], f[j][1]);//不选节点u,则判断选子节点j还是不选子节点j时大,选择较大的结果加上即可
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &happy[i]);
memset(h, -1, sizeof h);
for (int i = 0; i < n - 1; i++)//n个节点n-1条边;读入节点间的关系
{
int a, b;
scanf("%d%d", &a, &b);//b是a的父亲节点
add(b, a);
has_fa[a] = true;//a有父亲节点,置true
}
int root = 1;
while (has_fa[root]) root++;//当has_fa[root]为false时说明root节点没有父节点,则找到了根节点
dfs(root);//由根节点开始找
printf("%d\n", max(f[root][0], f[root][1]));//根节点选或不选,取max
return 0;
}