2013寒假练习 1018:没有上司的聚会

地址:http://acm.bit.edu.cn/mod/programming/view.php?a=504

树形DP好题。终于独立做出一道题。。

题意:给出一棵树的节点的权值,取一个节点集满足没有节点有父子关系,求这个节点集总权值的最大值。

由于当前节点是否取影响其父亲的DP取值,故DP时要分取和不取两种情况。状态转移方程还是比较好想的,可以参见代码。

然后就是具体处理,我是用父亲表示法存树(parent),初始先将所有叶子节点入队,然后依次更新它们的父亲的DP值;用辅助数组child找出他们的父亲并入队。。一直到树根,输出树根的两个DP值中最大的那个。

#include<iostream>
#include<queue>
using namespace std;
#define SIZE 100005
int child[SIZE];   //未被处理的孩子个数 
int parent[SIZE];  //记录父亲
int dp[2][SIZE];   //dp[0][]表示不选该节点时子树的最大价值。dp[1][]表示选
int a[SIZE];
int main()
{
	int n,i,now,t1,t2;
	while(~scanf("%d",&n))
	{
		memset(child,0,sizeof(child));
		memset(dp,0,sizeof(dp));
		for(i=1;i<=n;i++)  scanf("%d",&a[i]);
		for(i=1;i<=n-1;i++)
		{
			scanf("%d%d",&t1,&t2);
			parent[t1]=t2,child[t2]++;
		}
		queue<int>q;
		for(i=1;i<=n;i++)
		{
			if(!child[i])         //找到初始处于最底层的(没有孩子),初始化边界条件并入队
			{
				dp[0][i]=0,dp[1][i]=a[i];
				q.push(i);
			}                        
		}
		for(i=1;i<n;i++)       //对当前已得到DP值的该层节点,以之更新上一层的值
		{
			now=q.front();
			dp[0][parent[now]]+=dp[0][now]>dp[1][now]?dp[0][now]:dp[1][now];          //状态转移方程。不取根就可以取或不取孩子,取了根只能不取孩子
			dp[1][parent[now]]+=dp[0][now];
			child[parent[now]]--;                                                    
			if(child[parent[now]]==0)             //若上一层某节点孩子全部处理完毕,则入队
			{
				q.push(parent[now]);  
				dp[1][parent[now]]+=a[parent[now]];       //dp[1][]因为取了树根最后还要加上树根的值
			}
			q.pop();
		}
		printf("%d\n",dp[0][q.front()]>dp[1][q.front()]?dp[0][q.front()]:dp[1][q.front()]);
	}
	return 0;
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值