您的位置:首页 > 其它

HDU 1520 Anniversary party 树形dp 入门

2016-05-26 20:32 513 查看
输入n个结点,接下去的n行,表示1-n的每个结点分别具有的活跃值,在接下来去的n-1行,输入a,b,表示b是a的上司

输出:

由于直接有上司和下属关系的两个人不能同时参加party, 求出能让party活跃值最大的方案(求出最大的活跃值即可).

这是一个有向树。

每个结点有两种状态,参加和不参加,用0表示不参加,1表示参加

dp[i][1]表示第i个参与者参加了,dp[i][0]表示第i个参与者没有参加。

状态转移方程:dp[u][0] += max (dp[v][0], dp[v][1]) :表示上司没参加,其员工可以参加可以不参加

dp[u][1] += dp[v][0] : 表示若上司参加了,其员工一定不会参加
#include <cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<cstdlib>
#include<vector>
#define LL unsigned long long
#define bug puts("***********")
#define INF 0x3f3f3f3f

using namespace std;
vector<int>vec[6010];
int dp[6010][2];
int val[6100];
int vis[6100];
int DFS(int x)
{
if(vis[x]) return max(dp[x][0],dp[x][1]);
int sum=0;
dp[x][0]=0;
dp[x][1]=val[x];
vis[x]=1;
for(int i=0;i<vec[x].size();i++)
{
DFS(vec[x][i]);
dp[x][0]+=max(dp[vec[x][i]][0],dp[vec[x][i]][1]);
dp[x][1]+=dp[vec[x][i]][0];
}
return max(dp[x][0],dp[x][1]);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(vec,0,sizeof(vec));
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
int x,y;
while(scanf("%d%d",&x,&y),x+y)
{
vec[y].push_back(x);
}
int sum=0;
for(int i=1;i<=n;i++)
sum=max(sum,DFS(i));
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: