第6届蓝桥杯

10题 生命之树(树形dp)
给定一颗无根树,求出一个字数,所有节点的权值之和最大。求出最大的数是多少。

题目思路:

对于每个结点的决策有2种,分别是选择和不选择,那么我们定义dp[ i ][ 0 ] 和 dp[ i ][ 1 ]分别表示不选择(选择) i 结点能得到的最大权值和。

状态转移方程是:dp [ i ] [ 1 ] = sum(max(dp[ j ][ 1 ] , dp[ j ][ 0 ]));  j 是 i 的孩子结点 。

       dp[ i ][ 0 ] = 0;
#include<cstdio>
#include<cstring>
#include<vector>
#define N 100005
using namespace std;
vector<int> node[N];
// dp[i][0],dp[i][1];
// 分别表示选i结点和不选能得到的最大分数 
int dp[N][2];
int v[N],vis[N];
int n,a,b;
void dfs(int u){
	dp[u][1] = v[u];
	dp[u][0] = 0;
	vis[u]=1;
	for(int i=0 ;i<node[u].size();i++){
		if(!vis[node[u][i]]){
			dfs(node[u][i]);
	
			dp[u][1] += max(dp[node[u][i]][1],dp[node[u][i]][0]);
		
		}else{
			dp[u][1] = max(dp[u][1],v[u]);
			dp[u][0] = max(dp[u][0],0);
		}
	}
} 
 
void init(){
	memset(v,0,sizeof(v));
	memset(dp,0,sizeof(dp));
	scanf("%d",&n);
	for(int i=1 ;i<=n ;i++){
		scanf("%d",&v[i]);
	}
	for(int i=1 ;i<n ;i++){
		scanf("%d%d",&a,&b);
		node[a].push_back(b);
		node[b].push_back(a);
	}
}
 
int main(){
	init();
	
	dfs(1);
	int ans = -1;
	for(int i=1 ;i<=n ;i++){
//		printf("dp[%d][1]:%d\n",i,dp[i][1]);
//		printf("dp[%d][0]:%d\n",i,dp[i][0]);
		ans = max(ans,dp[i][1]);
		ans = max(ans,dp[i][0]);
	}
	printf("%d\n",ans);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值