AcWing 285. 没有上司的舞会
原题链接
简单
作者:
阿飞被注册了
,
2021-06-03 16:21:13
,
所有人可见
,
阅读 288
思路及具体过程都在代码里面了 respect!
C++ 代码
//状态表示:f[u][0]--所有从以u为根的子树中选择,并且不选择u这个点的方案
// f[u][0]--所有从以u为根的子树中选择,并且选择u这个点的方案。
//状态计算:f[u][1] += f[j.i][0], f[u][0] += max(f[j.i][0], f[j.i][1]). j.i为u的直系下属(即:儿子)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 6e3+10;
int e[N], h[N], idx, ne[N];//链表存树--快忘完了qwq
int f[N][2];
int hpy[N];
bool is_father[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u)
{
f[u][1] = hpy[u];
for(int i = h[u]; i != -1; i = ne[i])//遍历u的每个儿子
{
int j = e[i];
dfs(j);//递归找到最底层的,然后再往回倒->找到最终的ans
f[u][0] += max(f[j][0], f[j][1]);//当u不选时,在u的儿子选择与不选择两种状态中取最大
f[u][1] += f[j][0];//当u选择时,u的儿子一定不能选
}
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) h[i] = -1;//初始化链表
for(int i = 1; i <= n; i++)
cin >> hpy[i];
for(int i = 1; i < n; i++)
{
int a, b;
cin >> a >> b;
add(b, a);//b是a的father
is_father[a] = true;//a存在father
}
int root = 1;
while(is_father[root]) root++;//找根节点
dfs(root);//递归
cout << max(f[root][0], f[root][1]);//root选择与不选择两种状态中最大的就是答案。
return 0;
}