AcWing 1220. 生命之树【树形DP】
原题链接
中等
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1000010, M = N * 2; // 双向边
typedef long long ll;
int w[N]; // 记录权值
int h[N],e[N],ne[M];
int idx; // 序号值
ll f[N]; // 状态数组,f[i]表示从结点一直往下的连通块的和值最大值
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a], h[a] = idx;
idx++;
}
void dfs(int u, int fa) // 当前结点和它的父节点
{
f[u] = w[u]; // 赋权值
for(int i = h[u];i != -1; i = ne[i]) // 遍历该结点的子节点
{
int j = e[i]; // 其中一个子节点
if(j != fa) // 防止回溯
{
dfs(j,u); // 先往下递归
f[u] += max(0ll,f[j]); // 加上子节点对应的状态(等上面语句递归完后)
}
}
}
int main()
{
int n;
cin >> n;
memset(h,-1,sizeof h);
for(int i = 1; i <= n;i++) // 输入n个点的权值
{
scanf("%d",&w[i]);
}
for(int i = 1; i < n;i++)
{
int a, b;
scanf("%d%d",&a,&b);
add(a,b), add(b,a);
}
dfs(1,-1);
// 遍历最大值
ll res = f[1];
for(int i = 2; i <= n;i++)
res = max(res,f[i]);
cout << res;
return 0;
}