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;
}



转载于:https://www.cnblogs.com/E-star/archive/2012/02/11/2346758.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值