树形dp----没有上司的舞会

没有上司的舞会

题意概述

  1. 每一个点都有一个权值
  2. 对于一个点i,如果选了它,那么它的儿子就不能选了。如果不选它,那么它的儿子可选可不选
  3. 问怎么选,使得总权值和最大

思路

  1. 对于一个点,如果它的父亲选了,那么它一定选不了
  2. 如果它的父亲没有选,它就可以选也可以不选
  3. 那到底选还是不选---选一个最有利的情况
  4. 那么每个点就有两种状态了:选或不选
  5. 标识不选,标识选
  6. 不选i点时,i点及其子树能选出来的最大价值 选i点时,i点及其子树能选出来的最大价值
  7. 那么最终结果就是
  8. 状态转移:对于点不选,那么它的儿子可选可不选,
    对于点选了,那么它的儿子就不能选了,
  9. 边界情况:对于叶子节点

代码

// 没有上司的舞会
#include <bits/stdc++.h>
#define endl '\n'
// #define int long long
using lli = long long;
using ull = unsigned long long;
inline int read()
{
    int x = 0, flag = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if (ch == '-')
        {
            flag = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * flag;
}

int val[6004];
int dp[6004][2];
std::vector<int> t[6004];
void dfs(int s, int fa)
{
    dp[s][0] = 0, dp[s][1] = val[s]; // 每个点的初始条件,顺带把边界也处理了
    for (int i = 0; i < t[s].size(); i++)
    {
        int j = t[s][i];
        if (j == fa) continue;
        dfs(j, s);
        dp[s][0] += std::max(dp[j][0], dp[j][1]);
        dp[s][1] += dp[j][0];
    }
}

signed main()
{
    int n = read();
    for (int i = 1; i <= n; i++)
    {
        val[i] = read();
    }
    int u = 0, v = 0;
    for (int i = 1; i <= n - 1; i++)
    {
        u = read(), v = read();
        t[u].push_back(v);
        t[v].push_back(u);
    }
    dfs(1, 0);
    std::cout << std::max(dp[1][0], dp[1][1]);
    return 0;
}
全部评论

相关推荐

06-12 16:50
已编辑
小米_软件开发(准入职员工)
晓沐咕咕咕:评论区没被女朋友好好对待过的计小将可真多。觉得可惜可以理解,毕竟一线大厂sp。但是骂楼主糊涂的大可不必,说什么会被社会毒打更是丢人。女朋友体制内生活有保障,读研女朋友还供着,都准备订婚了人家两情相悦,二线本地以后两口子日子美滋滋,哪轮到你一个一线城市房子都买不起的996清高计小将在这说人家傻😅
点赞 评论 收藏
分享
05-23 20:31
已编辑
武汉大学 Java
内向的柠檬精在研究求职打法:注意把武大标粗标大 本地你俩不是乱杀
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务