[洛谷]P1352 没有上司的舞会 (#树形dp)

题目描述

某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入输出格式

输入格式:

第一行一个整数N。(1<=N<=6000)

接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)

接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。

最后一行输入0 0

输出格式:

输出最大的快乐指数。

输入输出样例

输入样例#1

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

输出样例#1

5

思路

超级棒的树形dp题目。

令dp[i][0]为以i为根的子树,且如果i不参加的最大快乐值;dp[i][1]为以i为根的子树,且如果i参加的最大快乐值。

显然,如果你不去,那你的下属想去就去。

dp[i][0]=sum(max(dp[son][0],dp[son][1])) 其中son是i的儿子

显然,如果你去了,那你的下属肯定不能去。

dp[i][1]=sum(dp[son][0])+happy[i] 其中son是i的儿子

答案为max(dp[root][0],dp[root][1])。

#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
int happy[6001],a[6001],dp[6001][2],n,m,s;
bool vis[6001];
vector<int> son[6001];
void dfs(int i)
{
	register int j;
	dp[i][0]=0;
	dp[i][1]=happy[i];
	for(j=0;j<son[i].size();j++)//遍历所有儿子节点 
	{
		int Son=son[i][j];
		dfs(Son);
		dp[i][0]+=max(dp[Son][0],dp[Son][1]);
		dp[i][1]+=dp[Son][0];
	}
}
signed main() 
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>happy[i];
	}
	for(i=1;i<=n-1;i++)//叶子节点没有儿子 
	{
		int fa,Son;
		cin>>Son>>fa;
		son[fa].push_back(Son);
		vis[Son]=1;
	}
	int root;
	for(i=1;i<=n;i++)//找根 
	{
		if(vis[i]==0)
		{
			root=i;
			break;
		}
	}
	dfs(root);
	cout<<max(dp[root][0],dp[root][1])<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值