1220. 生命之树
树状DP vector容器
从1点开始遍历树状图,最后求出最大值
w[ i ]代表权值,book[ i ]记录是否经过节点 i,dp[ i ]记录以节点 i 为父节点的最大权值
b[ i ]记录与节点 i 联通的节点(不包括节点 i 的父节点)
从一个结点开始b[ i ]只计算子节点的最大值,不用考虑父节点,
因为是树状结构、无向图,所以不存在联通环,因此遍历一遍总能找到最优解
父节点加子节点时有三种情况
1.加子节点以及子节点的子节点(子 1 孙 1 1)
2.加子节点(子 1 孙 -1 -1)
3.不加子节点(子 -1 孙 -1 -1)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=100010;
ll w[N],book[N],dp[N];
vector<int>b[N];
void dfs(int x)
{
dp[x]=w[x];
book[x]=1;
for(int i=0;i<b[x].size();i++)
{
if(book[b[x][i]]==0) dfs(b[x][i]);//判断是否计算过这个点
else continue;//如果计算过说明这个点是父节点,目前不用计算
ll m=max(dp[b[x][i]],w[b[x][i]]);
dp[x]+=max(m,0ll);//判断是否需要加子节点
}
}
int main()
{
int i,n;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%lld",&w[i]);//权值
for(i=1;i<n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
b[x].push_back(y);//无向图
b[y].push_back(x);//无向图
}
dfs(1);//从1点开始遍历
ll m=w[1];//最终数据可能大于int范围
for(i=1;i<=n;i++)
m=max(m,dp[i]);//寻找最大值
printf("%lld\n",m);
return 0;
}