HDU 1520 Anniversary party 树形dp 入门

来源:互联网 发布:godaddy如何转入域名 编辑:程序博客网 时间:2024/05/16 04:47

输入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 0x3f3f3f3fusing 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;}


0 0