1220. 生命之树(树状DP)

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值