1. 程式人生 > >A - Anniversary party HDU - 1520(沒有上司的舞會)

A - Anniversary party HDU - 1520(沒有上司的舞會)

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 T lines that describe a supervisor relation tree. Each line 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

樹形dp入門題目,上司和下屬不能同時出現。。就要動態規劃下去,看看怎樣的佈置才會使總價值最高。我覺得樹形dp的題目還是需要用vector,雖然用陣列啥的在poj上可以過去,但是在hdu上過不了。卡資料卡的太厲害了。
程式碼如下:

//正確程式碼:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn=6005,inf=1<<30;
int dp[maxn][2];
int w[maxn],in[maxn];
int n,m;
vector<int>G[maxn];
void dfs(int u,int fa)
{
 
    dp[u][1]=w[u];
    dp[u][0]=0;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(v==fa) continue;
        dfs(v,u);
        dp[u][1]+=dp[v][0];
        dp[u][0]+=max(dp[v][1],dp[v][0]);
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        int rt=1;
        for(int i=0;i<=n;i++) G[i].clear(),in[i]=0;
        for(int i=1;i<=n;i++) scanf("%d",&w[i]);
        int from,to;
        while(scanf("%d%d",&from,&to),from+to)
        {
            G[to].push_back(from);//建一條上司到下屬的邊
            in[from]++;
        }
        for(int i=1;i<=n;i++)
        if(in[i]==0) {rt=i;break;}
        dfs(rt,-1);
        int ans=max(dp[rt][0],dp[rt][1]);
        printf("%d\n",ans);
    }
    return 0;
}

但是我還是覺得把那個程式碼貼出來,畢竟在poj上可以過去哦
程式碼如下:
(錯誤程式碼)在hdu上過不去的,嗚嗚嗚

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxx=6e3+10;
int dp[maxx][2];
int vis[maxx];
int ins[maxx];
int f[maxx];

void init()
{
	memset(dp,0,sizeof(dp));
	memset(vis,0,sizeof(vis));
	memset(ins,0,sizeof(ins));
	memset(f,0,sizeof(f));
}

int n,l,k,top;

void dfs(int top)
{
	vis[top]=1;
	for(int i=1;i<=n;i++)
	{
		if(vis[i]==0&&f[i]==top)
		{
			dfs(i);
			dp[top][1]+=dp[i][0];
			dp[top][0]+=max(dp[i][0],dp[i][1]);
		}
	}
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=1;i<=n;i++) cin>>dp[i][1];
		while(scanf("%d%d",&l,&k),l+k)
		{
			f[l]=k;
			ins[l]++;
		}
		for(int i=1;i<=n;i++)
		{
			if(ins[i]==0)
			{
				top=i;
				break;
			}
		}
		dfs(top);
		cout<<max(dp[top][1],dp[top][0])<<endl;
	}
}

努力加油a啊,(o)/~