洛谷 P1352 没有上司的舞会(树形DP)

题目链接

这是一道终极经典的树形DP的例题。

树形dp就是将DP的数据放到了一棵树上。每个父节点与其子节点的值有关。推出如何建树和递推公式即可。

f[i][j].(j=1/0)i表示这是谁,j为1时表示来,0时表示不来。这个式子表示i来或不来时的最大快乐值。

设k为他的下属。

则f[i][1]+=f[k][0],f[i][0]+=max(f[k][0],f[k][1]).

即当i来时,j肯定不能来。则加上k不能来时的最大快乐值。

当i不来时,j来不来都有可能。则加上j来和不来中的最大值。

AC代码如下:

#include<cstdio>
#include<algorithm> 
#include<vector>
using namespace std;
typedef long long ll;
int n,h[6005],v[6005],f[6005][2]; 
vector<int> son[6005];
void dp(int x){
    f[x][0]=0;
    f[x][1]=h[x];
    for(int i=0;i<son[x].size();i++){
        int y=son[x][i];
        dp(y);
        f[x][0]+=max(f[y][0],f[y][1]);
        f[x][1]+=f[y][0];
    }
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&h[i]);
    }
    for(int i=0;i<n-1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        son[y-1].push_back(x-1);
        v[x-1]=1;
    }
    int root;
    for(int i=0;i<n;i++)
        if(!v[i]){
            root=i;
            break;
        }
    dp(root);
    printf("%d\n",max(f[root][0],f[root][1]));
    return 0;
}

 

posted @ 2021-02-20 19:21  mikku  阅读(36)  评论(0)    收藏  举报