POJ 2342 Anniversary party(树形DP)

题目要求在保持员工与其直接上级不同时参加周年庆祝会的情况下,选出员工集合,使他们的评分总和最大。利用树形动态规划算法,计算每个节点不选和选时子树的最大评分,从根节点递归进行计算,以达到最大评分的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源:http://poj.org/problem?id=2342

Anniversary party

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 10684

Accepted: 6121

Description

There is going to be a party to celebrate the80-th Anniversary of the Ural State University. The University has ahierarchical structure of employees. It means that the supervisor relationforms a tree rooted at the rector V. E. Tretyakov. In order to make the partyfunny for every one, the rector does not want both an employee and his or herimmediate supervisor to be present. The personnel office has evaluatedconviviality of each employee, so everyone has some number (rating) attached tohim or her. Your task is to make a list of guests with the maximal possible sumof guests' conviviality ratings.

Input

Employees are numbered from 1 to N. A first lineof input contains a number N. 1 <= N <= 6 000. Each of the subsequent Nlines contains the conviviality rating of the corresponding employee.Conviviality rating is an integer number in a range from -128 to 127. Afterthat go N – 1 lines that describe a supervisor relation tree. Each line of thetree specification has the form: 
L K 
It means that the K-th employee is an immediate supervisor of the L-themployee. Input is ended with the line 
0 0 

Output

Output should contain the maximal sum of guests'ratings.

Sample Input

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

SampleOutput

5

Source

Ural State University InternalContest October'2000 Students Session

 -----------------------------------------------------

思路

题意:在一棵节点带权的树中选择若干的节点,满足如果一个节点被选中,则它的父节点不能同时被选中。存在一种选择方案,使得选中的节点权值之和最大,求该最大权值。

算法:树形dp

dp[u][0]: 以节点u为根的子树的不取节点u的权

dp[u][1]: 以节点u为根的子树的取节点u的权

dp[u][0] = sum_v(max(dp[v][0], dp[v][1])

dp[u][1] = sum_v(dp[v][0]) + weight[u]              

其中vu的子节点

具体实现采用递归,从根节点开始递归

-----------------------------------------------------

代码 

//树形dp
//dp[u][0]: 以节点u为根的子树的不取节点u的权; dp[u][1]: 以节点u为根的子树的取节点u的权
// dp[u][0] = sum_v(max(dp[v][0], dp[v][1])
// dp[u][1] = sum_v(dp[v][0]) + weight[u]			其中v是u的子节点

#include<iostream>
#include<fstream>
#include<vector>
using namespace std;

const int NMAX = 6005;
int rat[NMAX] = {};						// 节点的权
vector<int> son[NMAX] = {};				// 节点的子节点集
int dp[NMAX][2] = {};					// 树形dp[u][0]: 以节点u为根的子树的不取节点u的权; dp[u][1]: 以节点u为根的子树的取节点u的权
bool vis[NMAX] = {};					// 是否是某个节点的子节点(用于找根节点)

void dfs(int u)
{
	int i= 0, v;
	dp[u][0] = 0;						// dp[u][0]不取u自己的权
	dp[u][1] = rat[u];					// dp[u][1]要取u自己的权
	if (son[u].size() > 0)				// 如果u不是叶子节点
	{
		for (i=0; i<son[u].size(); i++)
		{
			v = son[u].at(i);			// v是u的一个子节点
			dfs(v);						// 递归求解以v为根的子树的权
			dp[u][0] += max(dp[v][1], dp[v][0]);	// 不取u, 则v取不取都可以
			dp[u][1] += dp[v][0];		// 取u, 则只能不取v
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin ("2342.txt");
	int n,i,u,v,root;
	fin >> n;
	for (i=0; i<n; i++)
	{
		fin >> rat[i];
	}
	while (fin >> v >> u)
	{
		if (u==0 &&v==0)
		{
			break;
		}
		son[--u].push_back(--v);
		vis[v] = 1;
	}
	fin.close();
	for (i=0; i<n; i++)							// 不是任何节点的子节点的节点就是根节点
	{
		if (!vis[i])
		{
			root = i;
			break;
		}
	}
	dfs(root);									// 从根节点开始递归
	cout << max(dp[root][0], dp[root][1]);		// 输出根节点dp的较大者
	return 0;
#endif
#ifdef ONLINE_JUDGE
	int n,i,u,v,root;
	cin >> n;
	for (i=0; i<n; i++)
	{
		cin >> rat[i];
	}
	while (cin >> v >> u)
	{
		if (u==0 &&v==0)
		{
			break;
		}
		son[--u].push_back(--v);
		vis[v] = 1;
	}
	for (i=0; i<n; i++)							// 不是任何节点的子节点的节点就是根节点
	{
		if (!vis[i])
		{
			root = i;
			break;
		}
	}
	dfs(root);									// 从根节点开始递归
	cout << max(dp[root][0], dp[root][1]);		// 输出根节点dp的较大者
#endif
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值