HDU 1520 树形dp裸题

1、HDU 1520  Anniversary party  

2、总结:第一道树形dp,有点纠结

题意:公司聚会,员工与直接上司不能同时来,求最大权值和

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define max(a,b) a>b?a:b
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
const int N=6010;

struct Eage
{
    int from,to;
    int next;
}eage[N<<1];

int val[N],out[N];
int dp[N][2];   //dp[i][0]表示i不去,dp[i][1]表示i去

int ans,head[N];    //head记录边的次序
void add_eage(int a,int b)  //难点,理解边,构树
{
    eage[ans].from=a;
    eage[ans].to=b;
    eage[ans].next=head[b];
    head[b]=ans++;
}

void dfs(int root)
{
    dp[root][0]=0;
    dp[root][1]=val[root];
    for(int i=head[root];i!=-1;i=eage[i].next){     //dfs所有指向root点的边
        int s=eage[i].from;
        dfs(s);
        //状态转移。root去,他的下属就不能去;root不去,就取他下属去或不去的最大值
        dp[root][0]+=max(dp[s][0],dp[s][1]);
        dp[root][1]+=dp[s][0];
    }
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
        }

        memset(out,0,sizeof(out));
        memset(head,-1,sizeof(head));
        int a,b;
        ans=0;
        while(scanf("%d%d",&a,&b),a||b){
            out[a]++;
            add_eage(a,b);
        }

        int root;
        for(int i=1;i<=n;i++){
            if(!out[i]){    //出度为0即根结点
                root=i;
                break;
            }
        }

        memset(dp,0,sizeof(dp));
        dfs(root);
        printf("%d\n",max(dp[root][0],dp[root][1]));

    }

    return 0;
}
View Code

 

posted @ 2016-08-25 23:02  v9fly  阅读(263)  评论(0编辑  收藏  举报