• E. Hanging Hearts(树形dp)


    题目

    题意

    给定一棵树,结点数为n。根节点为1。现在可以选择任意一个n的排列a,给这棵树每个节点赋值。使得赋值后,树上每个节点有一个权值,且互不相同。

    给定一个空数组s,再执行以下过程

    • 从树上选择一个没有孩子节点的节点x,将其权值添加到s数组末尾。
    • 如果节点x不是根节点,且当前节点的父节点,权值大于节点x的权值,则更新父节点的权值为节点x的权值。
    • 从树上移除节点x

    求出,最终得到的数组s,最长非递减子序列,最大长度。

    问,如果采用最佳策略执行上述操作,数组s的最长非递减子序列,最大长度是多少。

    思路

    嗯,一道封装了一层皮的树形dp,,

    几个观察点

    • 叶子节点,不取白不取。如果最终得到的最长非递减子序列为b1,b2,…,bk,且bi对应的节点x,不是叶子节点,那么我们可以令节点x的一个孩子节点,的权值为bi。这样,就可以构造出b1,b2,…bi,bi,…,bk的非递减子序列,长度多了1。
    • 同深度的节点x,y,如果它们对应的权值bi, bj都存在于最长非递减子序列中,那么节点x,y的父节点z,对应的权值v,不能出现在最长非递减子序列中。
      • 证明:不妨设bi

    利用上述2个结论。我们可以构造dp转移方程,
    令dp[u][0]表示不取当前节点时,该子树能得到的最大的非递减子序列的长度,
    dp[u][1]表示取当前节点,该子树能得到的最大的非递减子序列的长度。

    dp[u][0]只要累加所有子树的dp最大值即可
    dp[u][1]实际就是节点u的深度。

    dp[u][0] += max(dp[v][1], dp[v][0]);
    dp[u][1] = max(dp[u][1], dp[v][1] + 1);
    
    • 1
    • 2

    代码

    #include 
    using namespace std;
    #define ll long long
    #define pcc pair<char, char>
    #define pii pair<int, int>
    #define inf 0x3f3f3f3f
    const int maxn = 200010;
    const int mod = 998244353;
    
    
    vector<int> ve[maxn];
    int n, p;
    int dp[maxn][2];
    void dfs(int u, int d) {
        if (!ve[u].size()) {
            dp[u][0] = 0;
            dp[u][1] = 1;
            return;
        }
        for (auto v: ve[u]) {
            dfs(v, d + 1);
        }
        dp[u][0] = 0;
        dp[u][1] = -1;
        for (auto v: ve[u]) {
            dp[u][0] += max(dp[v][1], dp[v][0]);
            dp[u][1] = max(dp[u][1], dp[v][1] + 1);
        }
        
    }
    void solve() {
        scanf("%d", &n);
        for (int i = 2; i <= n; ++i) {
            scanf("%d", &p);
            ve[p].push_back(i);
        }
        dfs(1, 1);
        printf("%d\n", max(dp[1][1], dp[1][0]));
    }
    int main() {
        int t = 1;
    //    scanf("%d", &t);
        int cas = 1;
        while (t--) {
    //		printf("cas %d:\n", cas++);
            solve();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    VictoriaMetrics时序数据库(TSDB)的使用
    建筑能源管理(5)——建筑能源审计和审计方法
    C# 使用SpecFlow创建BDD测试用例
    遥感影像正射矫正
    Java Future学习
    WoShop分销积分直播短视频商城全开源无加密商城源码
    看完年薪 30W~120W 程序员分别需要掌握的技能栈,我彻底悟了
    GaussDB之应用无损透明(ALT)
    java毕业设计餐饮类网站Mybatis+系统+数据库+调试部署
    从您输入网站 URL 到其在屏幕上完成加载的整个过程
  • 原文地址:https://blog.csdn.net/weixin_43918473/article/details/127624180