树型DP入门

题意:
某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。

思路:
任何一个点的取舍可以看作一种决策,那么状态就是在某个点取的时候或者不取的时候,以他为根的子树能有的最大活跃总值。分别可以用f[i,1]和f[i,0]表示第i个人来和不来。

当i来的时候,dp[i][1] += dp[j][0];//j为i的下属
当i不来的时候,dp[i][0] +=max(dp[j][1],dp[j][0]);//j为i的下属

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int father[6005],vis[6005],dp[6005][2],t;

void dfs(int node)
{
    int i,j;
    vis[node] = 1;
    for(i = 1;i<=t;i++)
    {
       if(!vis[i] && father[i] == node)
       {
           dfs(i);
           dp[node][1]+=dp[i][0];//node去,则i必不能去
           dp[node][0]+=max(dp[i][0],dp[i][1]);//node不去,取i去或不去的最大值
       }
    }
}

int main()
{
    int i,j,l,k,root;
    while(~scanf("%d",&t))
    {
        for(i = 1;i<=t;i++)
        scanf("%d",&dp[i][1]);
        root = 0;
        while(scanf("%d%d",&l,&k),l+k>0)
        {
            father[l] = k;//记录上司
            root = k;
        }
        memset(vis,0,sizeof(vis));
        dfs(root);
        printf("%d
",max(dp[root][1],dp[root][0]));
    }

    return 0;
}
原文地址:https://www.cnblogs.com/luckycode/p/5255644.html