HDU-1520 Anniversary party(树形DP)

题目大意:一棵树,每个节点都带权。从中取出一些节点,并且子节点不能与父节点同时取,求能取得的最大值。

题目分析:定义状态dp(u,0/1)表示u点不取/取。则状态转移方程为:

dp(u,1)=sum(dp(v,0))

dp(u,0)=sum(max(dp(v,1),dp(v,0)))

其中,v为u的子节点。

 

代码如下:

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

const int N=1005;

int n,w[N*6];
int dp[N*6][2];
bool flag[N*6];
vector<int>e[N*6];

void init()
{
	memset(flag,false,sizeof(flag));
	for(int i=1;i<=n;++i){
		scanf("%d",w+i);
		e[i].clear();
	}
	int a,b;
	while(scanf("%d%d",&a,&b)&&(a+b))
	{
		e[b].push_back(a);
		flag[a]=true;
	}
}

void dfs(int u)
{
	dp[u][1]=w[u];
	dp[u][0]=0;
	for(int i=0;i<e[u].size();++i){
		int v=e[u][i];
		dfs(v);
		dp[u][1]+=dp[v][0];
		dp[u][0]+=max(dp[v][1],dp[v][0]);
	}
}

void solve()
{
	int ans=0;
	for(int i=1;i<=n;++i){
		if(flag[i]) continue;
		dfs(i);
		ans+=max(dp[i][1],dp[i][0]);
	}
	printf("%d\n",ans);
}

int main()
{
	while(~scanf("%d",&n))
	{
		init();
		solve();
	}
	return 0;
}

  

posted @ 2016-03-31 21:05  20143605  阅读(145)  评论(0编辑  收藏  举报