POJ-2342::Anniversary party-树形DP

5 篇文章 0 订阅
1 篇文章 0 订阅

Description

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

Input

Employees are numbered from 1 to N. A first line of input contains a number N. 1 <= N <= 6 000. Each of the subsequent N lines contains the conviviality rating of the corresponding employee. Conviviality rating is an integer number in a range from -128 to 127. After that go N – 1 lines that describe a supervisor relation tree. Each l

ne of the tree specification has the form: 
L K 
It means that the K-th employee is an immediate supervisor of the L-th employee. 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

Sample Output

5


Source

本题题意::公司的员工们根据上下级关系可以形成树状的结构。在参加party中每个人都有一个rating,为了和谐,不让员工和他的直属上级同时存在,求最大的rating。

思路::用 fa 数组记录直属上司,vector son 数组直属下属,dp 数组记录最大的rating。dp[i][0]表示i不参加的最大rating、dp[i][1]表示i参加的最大rating。

那么状态转移方程为:dp[ i ][ 0 ] = dp[ i ][ 0 ] + max ( dp[ j ][ 0 ] , dp[ j ][ 1 ] );   j 为每一个 i 的直属下属

   dp[ i ][ 1 ] = dp[ i ][ 1 ] + dp[ j ][ 0 ] ; i 参加,i的所有直属下属都不能参加

代码::

#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3FFFFFFF
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
/***************************************
****************头文件******************
***************************************/
int fa[6005];//记录父亲节点
vector<int> son[6005];//记录所有的孩子节点
int dp[6005][2];//dp[i][0]表示i不参加的最大值dp[i][1]表示i参加的最大值
void dfs(int i)
{
	REP(j,son[i].size()){		//遍历每一个i的直属下属
		dfs(son[i][j]);			//至于这里遍历的不是 j ,而是son[i][j].我就错了好久,最后调试才发现问题
		dp[i][0] += max(dp[son[i][j]][0],dp[son[i][j]][1]);//看思路
		dp[i][1] += dp[son[i][j]][0];
	}
}
int main()
{
	int N;
	while(cin>>N)
	{
		REP(i,6005)	son[i].clear();//不能忘记初始化
		memset(dp,0,sizeof(dp);
		memset(fa,-1,sizeof(fa));
		REP2(i,1,N){
			cin>>dp[i][1];//当i参加时,最初应为自己的rating
		}
		int L,K;
		while(cin>>L>>K&&!(L==0&&K==0)){
			fa[L] = K;						//构建树,记录父亲结点
			son[K].PB(L);					//记录孩子节点
		}
		int ans = 0;						//记录答案,初始化
		/*REP2(i,1,N)
		REP(j,son[i].size())
		cout<<i<<" "<<son[i][j]<<endl;*/
		REP2(i,1,N){
			if(fa[i] == -1){				//当父亲节点为-1时找到root进行遍历
				dfs(i);
				ans+=max(dp[i][0],dp[i][1]);//如果有多个树根,要把每一个的最大rating加起来
			}
		}
		cout<<ans<<endl;//输出来就对了
	}
	return 0;
}
不算很难,思路清楚了,就一目了然。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值