AcWing 285. 没有上司的舞会(入门)

题目链接:点击这里
AcWing 285. 没有上司的舞会(入门)
AcWing 285. 没有上司的舞会(入门)

树形DP介绍:

  1. 给定一棵有 NNN 个节点的树(通常是无根树,也就是有 N1N-1N−1 条无向边),我们可以任选一个节点为根节点,从而定义出每个节点的深度和每棵子树的根。
  2. 在树上设计动态规划算法时,一般就以节点从深到浅(子树从小到大)的顺序作为DP的“阶段”。
  3. DP的状态表示中,第一维通常是节点编号(代表以该节点为根的子树)。
  4. 大多数时候,我们采用递归的方式实现树形动态规划。对于每个节点 xxx,先递归在它的每个子节点上进行DP,在回溯时,从子节点向节点 xxx 进行状态转移。

本题思路分析:

以节点编号(子树的根)作为DP状态的第一维。

因为一名职员是否愿意参加只跟他的直接上司是否参加有关,所以我们在每棵子树递归完成时,保留两个“代表信息":

  1. 根节点参加时整棵子树的最大快乐指数和
  2. 根节点不参加时整棵子树的最大快乐指数和

F[x,0]F[x,0]F[x,0] 表示从以 xxx 为根的子树中邀请一部分职员参会, 并且 xxx 不参加舞会时,快乐指数总和的最大值。此时,xxx 的子节点 sss(直接下属)可以参会,也可以不参会。
F[x,0]=max(F[s,0],F[s,1])F[x,0] = max(F[s, 0], F[s,1])F[x,0]=max(F[s,0],F[s,1])

F[x,1]F[x,1]F[x,1] 表示从以 xxx 为根的子树中邀请一部分职员参会, 并且 xxx 参加舞会时,快乐指数总和的最大值。此时,xxx 的所有子节点 sss(直接下属)都不能参会。
F[x,1]=H[x]+F[s,0]F[x,1]= H[x] +F[s, 0]F[x,1]=H[x]+F[s,0]

本题输入的是一棵有根树(指定了节点间的上下属关系),故我们需要先找出没有上司的节点 rootrootroot 作为根,DP的目标为 max(F[root,0],F[root,1])max(F[root, 0], F[root, 1])max(F[root,0],F[root,1])。时间复杂度 O(N)O(N)O(N)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 6010;

int n;

int e[N], w[N], ne[N], h[N], idx;       //数组模拟邻接表
bool st[N];
int f[N][2];


void add(int u, int v)
{
    e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}

void dfs(int u)
{
    f[u][0] = 0;
    f[u][1] = w[u];
    
    for(int i = h[u]; ~i; i = ne[i])     //枚举当前点的所有边
    {
        int j = e[i];
        dfs(j);
        f[u][0] += max(f[j][0], f[j][1]);
        f[u][1] += f[j][0];
    }
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &w[i]);
    
    memset(h, -1, sizeof h);
    for(int i = 1; i <= n - 1; ++i)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(b, a);
        st[a] = true;
    }
    
    int root = 1;
    while(st[root]) root++;     //寻找根节点
    
    dfs(root);
    
    printf("%d", max(f[root][0], f[root][1]));
    
    
    return 0;
}
AcWing 285. 没有上司的舞会(入门)AcWing 285. 没有上司的舞会(入门) 菜是原罪QAQ 发布了740 篇原创文章 · 获赞 112 · 访问量 13万+ 他的留言板 关注
上一篇:Android 开发技术周报 Issue#285


下一篇:OpenLayers学习笔记(十一)— 飞机速度矢量线预测