hdu 1520 Anniversary party 树形dp
http://acm.hdu.edu.cn/showproblem.php?pid=1520
学校举行周年纪念日party,要求是直接上司和下属关系的员工不能同时参,给出树形关系图,求怎样邀请的人的列表是的总rating最大。每个人都对应着一个rating
首先建立无向图,然后以以1节点为根节点,dfs从叶子往根推。。
dp[i][0] 表示i节点不邀请是的最大rating,dp[i][1]表示i节点要请示最大的rating
转台转移方程
dp[i][0] += max(dp[son[i]][1],dp[son[i]][0]); i没被邀请,所以他的孩子可以邀请也可以不邀请,我们只要最大rating的。。。
dp[i][1] += dp[son[i]][0]; i已经被邀请了所以我们只能要他的孩子没被邀请时的最大rating
注意dp的出事化。
View Code
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#define maxn 6007
using namespace std;
vector<int>g[maxn];
int dp[maxn][2],val[maxn];
bool visit[maxn];
void dfs(int rpos)
{
int i,num;
visit[rpos] = true;
int size = g[rpos].size();
if (size == 1 && rpos != 1) return ;//要注意根节点1的处理
for (i = 0; i < size; ++i)
{
num = g[rpos][i];
if(!visit[num])
{
visit[num] = true;
dfs(num);
//状态转移
dp[rpos][0] += max(dp[num][1],dp[num][0]);
dp[rpos][1] += dp[num][0];
}
}
//printf("@@%d %d %d\n",num,dp[rpos][1],dp[num][0]);
//printf(">>>%d %d %d\n",rpos,dp[rpos][0],dp[rpos][1]);
}
int main()
{
int n,i,x,y;
while(~scanf("%d",&n))
{
for (i = 1; i <= n; ++i)
{
scanf("%d",&val[i]);
g[i].clear();
}
while (scanf("%d%d",&x,&y))
{
if(!x && !y) break;
//建图
g[x].push_back(y);
g[y].push_back(x);
}
//测试图
/*for (i = 1; i <= n; ++i)
{
for (int j = 0; j < g[i].size(); ++j)
printf("%d ",g[i][j]);
printf("\n");
}*/
//dp的初始化
for (i = 1; i <= n; ++i)
{
dp[i][0] = 0;
dp[i][1] = val[i];
}
memset(visit,false,sizeof(visit));
dfs(1);
/*for (i = 1; i <= n; ++i)
printf("%d %d\n",dp[i][0],dp[i][1]);*/
printf("%d\n",max(dp[1][0],dp[1][1]));
}
return 0;
}