(树形DP入门题)Anniversary party(没有上司的舞会) HDU

题意:

有个公司要举行一场晚会。为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司等都可以邀请。已知每个人最多有唯一的一个上司。 
已知公司的每个人参加晚会都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。

思路:

树形DP入门题

①先设定:数组dp[i][0]为第i个人参加了舞会的时候这个子树的欢乐值之和

                  数组dp[i][1]为第i个人没参加舞会的时候这个子树的欢乐值之和

②由此我们可以推出对于i的状态转移方程为

            dp[i][0] = a[i]+ ∑dp[j][1]  (i为j的父亲节点)  

    dp[i][1] = ∑Max(dp[j][1],dp[j][0])  (i为j的父亲节点)

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
 using namespace std;
 const int maxn=6003;
 int a[maxn],dp[maxn][2];
 int n;
 vector<int> edge[maxn];
 void dfs(int x,int fa)
 {
     dp[x][0]=a[x],dp[x][1]=0;
     for(int i=0;i<edge[x].size();i++){
         if(edge[x][i]!=fa){
             dfs(edge[x][i],x);
             dp[x][0]+=dp[edge[x][i]][1];
             dp[x][1]+=max(dp[edge[x][i]][0],dp[edge[x][i]][1]);
         }    
     }
 }
 int main()
 {
     while(scanf("%d",&n)!=EOF){
         for(int i=1;i<=n;i++)
             scanf("%d",&a[i]);
         int l,k;
         for(int i=1;i<=n;i++)
             edge[i].clear();
         memset(dp,0,sizeof(dp));
         while(scanf("%d%d",&l,&k)&&l&&k){
             edge[l].push_back(k);
             edge[k].push_back(l);
         }
        dfs(1,0);
        printf("%d
",max(dp[1][0],dp[1][1]));
     }
    return 0;
 }
原文地址:https://www.cnblogs.com/overrate-wsj/p/12171553.html