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

题目链接:https://www.luogu.com.cn/problem/P1352
博客园食用链接:https://www.cnblogs.com/lonely-wind-/p/13488159.html

题目描述

某大学有 n 个职员,编号为 1 … n 1\ldots n 1n

他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。

现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 r i r_i ri,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。

所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入格式
输入的第一行是一个整数 n。

第 2 到第 ( n + 1 ) (n + 1) (n+1)行,每行一个整数,第 ( i + 1 ) (i+1) (i+1) 行的整数表示 i i i 号职员的快乐指数 r i r_i ri .第 ( n + 2 ) (n + 2) (n+2)到第 2 n 2n 2n 行,每行输入一对整数 l , k l, k l,k,代表 k 是 l 的直接上司。

输出格式
输出一行一个整数代表最大的快乐指数。

输入
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
输出
5

说明/提示
数据规模与约定
对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 6 × 1 0 3 1\leq n \leq 6 \times 10^3 1n6×103 − 128 ≤ r i ≤ 1 ≤ l , k ≤ n -128 \leq r_i\leq1 \leq l, k \leq n 128ri1l,kn,且给出的关系一定是一棵树。

emmm,蒟蒻发现自己的DP太辣鸡了。。。所以来练练DP,这题的话实际上应该算是树DP的入门题吧,转移还是挺好想的。

每次在每个节点都会有个选择,就是选还是不选,如果选的话,那么它的儿子节点就不能选,如果不选的话它的儿子节点就可以选,也就是说我们需要另开一维状态来记录每个节点是否选自己的情况,那么就很容易得出如下方程:

dp[x][0]+=max(0,max(dp[v][1],dp[v][0]));//如果不选当前节点,那么儿子节点可以任意选
dp[x][1]+=max(0,dp[v][0]);//如果选择当前节点,那么只能选择儿子节点不存在的情况

以下是AC代码:

#include 
using namespace std;

const int mac=1e4+10;

int a[mac],dp[mac][3],father[mac];
vector<int>g[mac];

void dfs(int x,int fa)
{
    dp[x][1]=a[x];
    for (auto v:g[x]){
        dfs(v,x);
        dp[x][0]+=max(0,max(dp[v][1],dp[v][0]));
        dp[x][1]+=max(0,dp[v][0]);
    }
}

int main(int argc, char const *argv[])
{
    int n; 
    scanf ("%d",&n);
    for (int i=1; i<=n; i++) scanf ("%d",&a[i]);
    for (int i=1; i<n; i++){
        int u,v;
        scanf ("%d%d",&u,&v);
        g[v].push_back(u);
        father[u]=v;
    }
    int root=0;
    for (int i=1; i<=n; i++) 
        if (!father[i]) {root=i; break;}
    dfs(root,0);
    printf("%d\n",max(dp[root][1],dp[root][0]));
    return 0;
}

你可能感兴趣的:(#,树形DP,树形DP)