【Luogu】P1352没有上司的舞会(树形DP)

  题目链接

  设f[i][0]表示第i个人不去舞会时子树的最大欢乐度,f[i][1]表示第i个人去舞会时子树的最大欢乐度。

  则有状态转移方程:f[i][0]+=∑max(f[to][0],f[to][1])

  f[i][1]+=∑f[to][0]

  其中to是i的所有直连子节点。

  初始化:f[i][1]=第i个人自己的欢乐度。

  我发现好像我做过的树形DP都是基于DFS搞的。这可能是个规律。

  

#include <cstdio>
#include <cstring>
#include<algorithm>
using namespace std;
int que[10000];
bool indl[10000];
struct Edge{
    int next,to;
}edge[100000];
int head[10000],num;
inline void add(int from,int to){
    edge[++num]=(Edge){head[from],to};
    head[from]=num;
}

int f[10000][2];

void dfs(int x){
    for(int i=head[x];i;i=edge[i].next){
        int to=edge[i].to;
        dfs(to);
        f[x][0]+=max(f[to][0],f[to][1]);
        f[x][1]+=f[to][0];
    }
    f[x][1]+=que[x];
    return;
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)    scanf("%d",&que[i]);
    for(int i=1;i<n;++i){
        int from,to;
        scanf("%d%d",&from,&to);
        add(to,from);
        indl[from]=1;
    }
    int start;
    for(int i=1;i<=n;++i){
        if(!indl[i]){
            start=i;
            break;
        }
    }
    dfs(start);
    printf("%d",max(f[start][0],f[start][1]));
    return 0;
}
原文地址:https://www.cnblogs.com/cellular-automaton/p/7523111.html