ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF 1249F Maximum Weight Subset - 树形DP

2019-11-12 22:00:53  阅读:287  来源: 互联网

标签:Subset Weight dep max CF pos int now dp


CF 1249F Maximum Weight Subset

题目链接:CF 1249F Maximum Weight Subset CF 1249F Maximum Weight Subset

算法标签: 深搜树形DP

题目描述:

给定一棵含 \(n\) 个节点的树,每个节点含一个点权 \(a[i]\) 。现在请你选出一些节点,使得这些节点的权值和最大并且这些节点中任意两个节点的距离都 \(>k\) 。并输出这个最大的权值。

输入第一行含两个整数 \(n,k\) ,之后是 \(n\) 个整数 \(a[i]\) ,之后是 \(n-1\) 行,每行两个整数,描述树的每条边。

题解:

树形DP

(CF div3最后一题很喜欢DP????? 逃~)

感觉上挺神仙的一道题,这个考场上应该是真的想不到………………

也是研究了小半天官方题解搞明白了。

下面开始正题:


我们设这棵树有根并且根是\(1\) ,之后来考虑以什么状态完成DP:

设\(dp[pos][dep]\)表示在\(pos\)的子树中符合条件的最大权值点集的权值和,并且保证这个最大权值点集中深度最小的点的深度\(\ge dep\)。(不太好理解…………)

之后的思路就是:我们需要计算 \(pos\) 的所有子节点的 \(dp[~][~]\),以此来更新 \(dp[pos][0\sim n]\)。

考虑当前的深度是 \(dep\) ,就有以下的两种想法:

  • 如果 \(dep == 0\),我们可以得到

    \(dp[pos][dep] = val[pos]+\sum_{to \in children(pos)}dp[to][max(0, k - dep - 1)]\),

  • 如果 \(dep!=0\),则可以得到 (\(to \in children(pos)~~~to \neq now\))

    \(dp[pos][dep]=max\{dp[pos][dep],dp[to][dep-1]+\sum_{now \in children(pos)}dp[now][max(dep-1,k-dep-1)]\}\)

之后我们要明确一个问题,在这其中我们包含着 \(k-dep-1\) 的计算,其实这里的 \(k = k_{初始}+1\) ,原因就是这里的计算保证的是每一个选择到的点都要与当前点的距离 \(\gt k\),而不是 \(\ge k\)。

上图理解一下:

CF 1249F Maximum Weight Subset p1.png

扔到整棵树里边:

CF 1249F Maximum Weight Subset p2.png

下面看代码:

AC代码

#include <bits/stdc++.h>

using namespace std;

const int N = 210;

vector <int> e[N];

int n, k, val[N];

int dp[N][N];

void add(int x, int y) {
    e[x].push_back(y);
    e[y].push_back(x);
}

void dfs(int pos, int pre) {
    dp[pos][0] = val[pos];
    for (int i = 0; i < (int)e[pos].size(); i ++ ) {
        int to = e[pos][i];
        if (to != pre) {
            dfs(to, pos);
        }
    }
    for (int dep = 0; dep < N; dep ++ ) {
        if (dep == 0) {
            for (int i = 0; i < (int)e[pos].size(); i ++ ) {
                int to = e[pos][i];
                if (to != pre) {
                    dp[pos][dep] += dp[to][max(0, k - dep - 1)];
                }
            }
        }
        else {
            for (int i = 0; i < (int)e[pos].size(); i ++ ) {
                int to = e[pos][i];
                if (to == pre) {
                    continue ;
                }
                int dis = dp[to][dep - 1];
                for (int i = 0; i < (int)e[pos].size(); i ++ ) {

                    int now = e[pos][i];
                    if (now == to || now == pre) {
                        continue ;
                    }
                    dis += dp[now][max(dep - 1, k - dep - 1)];
                }
                dp[pos][dep] = max(dp[pos][dep], dis);
            }
        }
    }
    for (int dep = N - 1; dep > 0; dep -- ) {
        dp[pos][dep - 1] = max(dp[pos][dep - 1], dp[pos][dep]);
    }
}

int main() {
    scanf("%d%d", &n, &k);
    k ++ ;
    for (int i = 1; i <= n; i ++ ) {
        scanf("%d", &val[i]);
    }
    for (int i = 1; i <= n - 1; i ++ ) {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
    }
    dfs(1, 0);
    cout << dp[1][0] << endl;
    return 0;
}

标签:Subset,Weight,dep,max,CF,pos,int,now,dp
来源: https://www.cnblogs.com/littleseven777/p/11845637.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有