CF1249F Maximum Weight Subset

洛谷评测传送门

题目描述

You are given a tree, which consists of nn vertices. Recall that a tree is a connected undirected graph without cycles.

Example of a tree.Vertices are numbered from 11 to nn . All vertices have weights, the weight of the vertex vv is a_va**v .

Recall that the distance between two vertices in the tree is the number of edges on a simple path between them.

Your task is to find the subset of vertices with the maximum total weight (the weight of the subset is the sum of weights of all vertices in it) such that there is no pair of vertices with the distance kk or less between them in this subset.

输入格式

The first line of the input contains two integers nn and kk ( 1 \le n, k \le 2001≤n,k≤200 ) — the number of vertices in the tree and the distance restriction, respectively.

The second line of the input contains nn integers a_1, a_2, \dots, a_na1,a2,…,a**n ( 1 \le a_i \le 10^51≤a**i≤105 ), where a_ia**i is the weight of the vertex ii .

The next n - 1n−1 lines contain edges of the tree. Edge ii is denoted by two integers u_iu**i and v_iv**i — the labels of vertices it connects ( 1 \le u_i, v_i \le n1≤u**i,v**in , u_i \ne v_iu**iv**i ).

It is guaranteed that the given edges form a tree.

输出格式

Print one integer — the maximum total weight of the subset in which all pairs of vertices have distance more than kk .

题意翻译

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

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

输入输出样例

输入 #1复制

输出 #1复制

输入 #2复制

输出 #2复制

题解:

题目翻译过来发第一篇题解(英语巨菜无所谓)

来讲一下正解:树上DP。

我们从0开始为节点编号,并设置0为根节点。

  • DP的状态是这样的:设\(dp[x][dep]\)为以\(x\)为根节点的子树中所有选中节点中深度最小的节点深度为\(dep\)时的最大价值(有点绕...请好好理解)

    这里要注意,我们定义的深度并不是整棵树的深度。因为动态规划是利用状态转移,所以我们定义的这个\(dep\)是在当前状态下的深度。通俗地讲,就是这棵子树的深度(子树根节点深度为0)。

那么我们开始考虑状态转移。这道题的一个限定条件(比较难搞)还有一个任意两点的距离都大于\(k\)。我们的状态转移(包括状态设置)都是考虑这个而进行的。

可以看出,对于每一个节点,它既统计了它自己的答案,又对它的合法的祖宗们(滑稽.jpg)的答案有贡献。所以,据此,我们考虑两种情况:第一种,当前的节点是子树的根,这个时候它是它的小家族的最大的祖宗,开始统计它的答案。第二种,当前的节点是儿子或孙儿或...这个时候它要对它上面的祖宗们贡献答案。

根据我们对状态的定义,在第一种情况下,当前节点的深度为0,那么当前节点的答案

\[dp[x][dep]=a[x]+\sum_{to\in children(x)}dp[to][max(0,k-dep)].
\]

在第二种情况下,我们则需要遍历\(x\)节点的所有儿子,然后挑出对答案贡献最大的儿子来更新答案。转移方程就是:

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

这个时候就能比较容易地想到用深搜解决问题。因为深搜的性质恰好满足:从上搜到低,在从低到上更新答案的过程。所以,我们把答案再从\(n-1\)号点跑回\(0\)号点即可。最终的答案就是\(dp[0][0]\)。

代码:

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int maxn=210;
  5. int n,k;
  6. int a[maxn],d[maxn],dp[maxn][maxn],tmp[maxn];
  7. int tot,head[maxn],nxt[maxn<<1],to[maxn<<1];
  8. void add(int x,int y)
  9. {
  10. to[++tot]=y;
  11. nxt[tot]=head[x];
  12. head[x]=tot;
  13. }
  14. void dfs(int x,int f)
  15. {
  16. dp[x][0]=a[x];
  17. for(int i=head[x];i;i=nxt[i])
  18. {
  19. int y=to[i];
  20. if(y!=f)
  21. dfs(y,x);
  22. }
  23. for(int i=0;i<n;i++)
  24. {
  25. if(!i)
  26. {
  27. for(int l=head[x];l;l=nxt[l])
  28. {
  29. int y=to[l];
  30. if(y==f)
  31. continue;
  32. dp[x][0]+=dp[y][k];
  33. }
  34. }
  35. else
  36. {
  37. for(int l=head[x];l;l=nxt[l])
  38. {
  39. int y=to[l];
  40. if(y==f)
  41. continue;
  42. int now=dp[y][i-1];
  43. for(int j=head[x];j;j=nxt[j])
  44. {
  45. int yy=to[j];
  46. if(yy==f || yy==y)
  47. continue;
  48. now+=dp[yy][max(i-1,k-i)];
  49. }
  50. dp[x][i]=max(dp[x][i],now);
  51. }
  52. }
  53. }
  54. for(int i=n;i>=1;i--)
  55. dp[x][i-1]=max(dp[x][i-1],dp[x][i]);
  56. }
  57. int main()
  58. {
  59. scanf("%d%d",&n,&k);
  60. for(int i=0;i<n;i++)
  61. scanf("%d",&a[i]);
  62. for(int i=0;i<n-1;i++)
  63. {
  64. int u,v;
  65. scanf("%d%d",&u,&v);
  66. u--,v--;
  67. add(u,v);
  68. add(v,u);
  69. }
  70. dfs(0,-1);
  71. printf("%d",dp[0][0]);
  72. return 0;
  73. }

CF1249F Maximum Weight Subset的更多相关文章

  1. 【CF1249F】Maximum Weight Subset(贪心)

    题意:给定一棵n个点带点权的树,要求从中选出一个点集,使得这些点两两之间距离都大于K,求最大点权和 n,K<=2e2,1<=a[i]<=1e5 思路:树形DP显然可做,极限是n方,然 ...

  2. codeforces#1249F. Maximum Weight Subset(树上dp)

    题目链接: http://codeforces.com/contest/1249/problem/F 题意: 一棵树的每个节点有个权值,选择一个节点集,使得任意点对的距离大于$k$ 求最大节点集权值, ...

  3. Codeforces 1249 F. Maximum Weight Subset

    传送门 设 $f[x][i]$ 表示 $x$ 的子树中,离 $x$ 最近的选择的节点距离为 $i$ 的合法方案的最大价值 设 $val[x]$ 表示节点 $x$ 的价值,首先有 $f[x][0]=va ...

  4. Codeforces 1249F Maximum Weight Subset (贪心)

    题意 在一颗有点权的树上,选若干个点,使得这些点两两距离大于k,且点权和最大 思路 贪心的取比较大的值即可 将所有点按照深度从大到小排序,如果当前点点权\(a[i]\)大于0,则将距离为k以内的所有点 ...

  5. F. Maximum Weight Subset(贪心or树形dp解法)

    题:https://codeforces.com/contest/1249/problem/F 题意:给一颗树,边权为1,节点有点权,问取到一个点集,俩俩之间路径超过k,是点权和最大 思路:贪心地取点 ...

  6. some problem

    CF1257F Make Them Similar $solution:$ 折半搜索后考虑如何维护两个数组的和,可以将 $A$ 中每个数减 $A_1$ ,$B$ 中每个数被减 $B_1$ ,$map$ ...

  7. Codeforces Round #595 (Div. 3)

    A - Yet Another Dividing into Teams 题意:n个不同数,分尽可能少的组,要求组内没有两个人的差恰为1. 题解:奇偶分组. int a[200005]; void te ...

  8. CF-595

    题目传送门 A .Yet Another Dividing into Teams sol:原先是用比较复杂的方法来解的,后来学弟看了一眼,发现不是1就是2,当出现两个人水平相差为1就分成两组,1组全是 ...

  9. Codeforces 828F Best Edge Weight - 随机堆 - 树差分 - Kruskal - 倍增算法

    You are given a connected weighted graph with n vertices and m edges. The graph doesn't contain loop ...

随机推荐

  1. JAVA实现二维码生成加背景图

    pom.xml依赖 <!-- 二维码生成 -->         <!-- https://mvnrepository.com/artifact/com.google.zxing/c ...

  2. Noip2016Day1T2 天天爱跑步

    题目链接 problem solution 这是一道一个顶六个的好题!!! 说一下各档部分分怎么写吧. 先看一下\(S_i=1\)和\(T_i=1\)的部分分怎么写. 如果\(S_i=1\) 当且仅当 ...

  3. Java类加载机制以及双亲委派模型

    一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允 ...

  4. 干货 | 国内互联网公司是如何做微服务实践的?(附PPT下载)

    微服务的概念最早由Martin Fowler与James Lewis于2014年共同提出,并随着Netflix最佳实践的发布而为业界所知.如今,在国内有了大量的微服务实践案例,5月18日,网易云联合云 ...

  5. PHP】获取客户端(浏览器)信息、获取客户端系统信息、获取服务器信息

    * 获取客户端浏览器信息 * @param null * @author https://blog.jjonline.cn/phptech/168.html * @return string */ f ...

  6. C++入门到理解阶段二基础篇(3)——C++数据类型

    目录 1.数据类型概述 2.基本的内置类型 整型 实型(浮点型) 字符型 转义字符 字符串型 c风格的字符串 c++风格的字符串 布尔类型bool 1.数据类型概述 使用编程语言进行编程时,需要用到各 ...

  7. Java正则表达式验证IP,邮箱,电话

     引言     java中我们会常用一些判断如IP.电子邮箱.电话号码的是不是合法,那么我们怎么来判断呢,答案就是利用正则表达式来判断了,废话不多说,下面就是上代码. 1:判断是否是正确的IP  1 ...

  8. hibernate中的merge()方法

    Hibernate提供有save().persist().savaOrUpdate()和merge()等方法来提供插入数据的功能.前三者理解起来较后者容易一些,而merge()方法从api中的介绍就可 ...

  9. WPF 使用动画设置特殊值的方法

    例如设置Visibility属性时: 第一种方式: <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIEleme ...

  10. java web工程的配置文件

    java web工程的配置文件 1.工程(源码依赖管理) 2.代码生成管理: 3.会话管理:servlet: 4.应用管理: 5.(分布式)资源管理:数据.数据库连接等. pom:源码管理工具 位置: ...