POJ-2342::Anniversary party-树形DP

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

Ural State University Internal Contest October'2000 Students Session

本题题意::公司的员工们根据上下级关系可以形成树状的结构。在参加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;
}
不算很难,思路清楚了,就一目了然。

你可能感兴趣的:(题解,dp,poj,party,anniversary)