题意看这篇博客:https://blog.csdn.net/dreaming__ldx/article/details/88418543

思路看这篇:https://blog.csdn.net/corsica6/article/details/88115948

有个坑点,不能深搜去找具体方案,不然 test14 会 MLE(或许是本蒟蒻写丑了)

代码:

  1. #include <bits/stdc++.h>
  2. #define LL long long
  3. #define pii pair<int, int>
  4. using namespace std;
  5. const int maxn = 200010;
  6. int head[maxn], Next[maxn * 2], ver[maxn * 2], tot;
  7. int a[maxn];
  8. LL dp[maxn][2], sum[maxn], f[maxn];
  9. bool v[maxn][2];
  10. bool res[maxn];
  11. vector<int> ans;
  12. bool is_leaf[maxn];
  13. void add(int x, int y) {
  14. ver[++tot] = y;
  15. Next[tot] = head[x];
  16. head[x] = tot;
  17. }
  18. void dfs1(int x, int fa) {
  19. int cnt = 0;
  20. f[x] = fa;
  21. for (int i = head[x]; i; i = Next[i]) {
  22. int y = ver[i];
  23. if(y == fa) continue;
  24. dfs1(y, x);
  25. sum[x] += dp[y][0];
  26. cnt++;
  27. }
  28. if(cnt == 0) {
  29. dp[x][0] = a[x];
  30. dp[x][1] = 0;
  31. is_leaf[x] = 1;
  32. return;
  33. }
  34. for (int i = head[x]; i; i = Next[i]) {
  35. int y = ver[i];
  36. if(y == fa) continue;
  37. dp[x][0] = min(dp[x][0], sum[x] - dp[y][0] + dp[y][1] + a[x]);
  38. dp[x][1] = min(dp[x][1], sum[x] - dp[y][0] + dp[y][1]);
  39. }
  40. dp[x][0] = min(dp[x][0], sum[x]);
  41. }
  42.  
  43. void bfs() {
  44. queue<pii> q;
  45. q.push(make_pair(1, 0));
  46. while(!q.empty()) {
  47. pii tmp = q.front();
  48. q.pop();
  49. int x = tmp.first, flag = tmp.second;
  50. if(v[x][flag]) continue;
  51. v[x][flag] = 1;
  52. if(flag == 0) {
  53. int pos = -1, cnt = 0;
  54. if(is_leaf[x]) {
  55. res[x] = 1;
  56. continue;
  57. }
  58. for (int i = head[x]; i; i = Next[i]) {
  59. int y = ver[i];
  60. if(y == f[x]) continue;
  61. if(dp[x][flag] == sum[x] - dp[y][0] + dp[y][1] + a[x]) {
  62. if(v[y][1]) continue;
  63. res[x] = 1;
  64. q.push(make_pair(y, 1));
  65. pos = y;
  66. cnt++;
  67. }
  68. }
  69. for (int i = head[x]; i; i = Next[i]) {
  70. int y = ver[i];
  71. if(v[y][0]) continue;
  72. if(y == f[x] || y == pos) continue;
  73. q.push(make_pair(y, 0));
  74. }
  75. if(cnt > 1 || (sum[x] == dp[x][0] && pos != -1)) {
  76. if(v[pos][0]) continue;
  77. q.push(make_pair(pos, 0));
  78. }
  79. } else {
  80. int pos = -1, cnt = 0;
  81. for (int i = head[x]; i; i = Next[i]) {
  82. int y = ver[i];
  83. if(y == f[x]) continue;
  84. if(dp[x][flag] == sum[x] - dp[y][0] + dp[y][1]) {
  85. if(v[y][1]) continue;
  86. q.push(make_pair(y, 1));
  87. pos = y;
  88. cnt++;
  89. }
  90. }
  91. for (int i = head[x]; i; i = Next[i]) {
  92. int y = ver[i];
  93. if(v[y][0]) continue;
  94. if(y == f[x] || y == pos) continue;
  95. q.push(make_pair(y, 0));
  96. }
  97. if(cnt > 1) {
  98. if(v[pos][0]) continue;
  99. q.push(make_pair(pos, 0));
  100. }
  101. }
  102. }
  103. }
  104. int main() {
  105. int n, x, y;
  106. scanf("%d", &n);
  107. for (int i = 1; i <= n; i++)
  108. scanf("%d", &a[i]);
  109. for (int i = 1; i < n; i++) {
  110. scanf("%d%d", &x, &y);
  111. add(x, y);
  112. add(y, x);
  113. }
  114. memset(dp, 0x3f, sizeof(dp));
  115. dfs1(1, -1);
  116. bfs();
  117. for (int i = 1; i <= n; i++) {
  118. if(res[i])
  119. ans.push_back(i);
  120. }
  121. printf("%lld %d\n", dp[1][0], ans.size());
  122. sort(ans.begin(), ans.end());
  123. for (int i = 0; i < ans.size(); i++)
  124. printf("%d ", ans[i]);
  125. printf("\n");
  126. }

最小生成树解法先留个坑在这。。。

补坑:

思路看这篇博客:https://www.cnblogs.com/river-flows-in-you/p/10596821.html

说一下我个人的理解:把每个叶子节点看成新图的顶点,对于原树中的每个顶点,我们可以计算出它影响哪些叶子节点,用差分的思想连边。只要求出了生成树就说明可以任意取,因为形成生成树之后,我们对每个点的赋值操作就可以类比在生成树上遍历的过程。

代码:

  1. #include <bits/stdc++.h>
  2. #define LL long long
  3. #define INF 0x3f3f3f3f
  4. using namespace std;
  5. const int maxn = 200010;
  6. int head[maxn], Next[maxn * 2], ver[maxn * 2], tot;
  7. int sz[maxn], cnt, l[maxn], r[maxn], a[maxn], f[maxn];
  8. bool v[maxn];
  9. struct Edge{
  10. int u, v, w, id;
  11. bool operator < (const Edge& rhs) const {
  12. return w < rhs.w;
  13. }
  14. };
  15. Edge b[maxn];
  16. void add(int x, int y) {
  17. ver[++tot] = y;
  18. Next[tot] = head[x];
  19. head[x] = tot;
  20. }
  21. void dfs(int x, int fa) {
  22. sz[x] = 1;
  23. l[x] = INF, r[x] = -1;
  24. for (int i = head[x]; i; i = Next[i]) {
  25. int y = ver[i];
  26. if(y == fa) continue;
  27. dfs(y, x);
  28. sz[x] += sz[y];
  29. l[x] = min(l[x], l[y]);
  30. r[x] = max(r[x], r[y]);
  31. }
  32. if(sz[x] == 1) {
  33. l[x] = r[x] = ++cnt;
  34. }
  35. b[x] = (Edge){l[x], r[x] + 1, a[x], x};
  36. }
  37. int get(int x) {
  38. if(x == f[x]) return x;
  39. return f[x] = get(f[x]);
  40. }
  41. int main() {
  42. int n, x, y;
  43. scanf("%d", &n);
  44. int sum = 0;
  45. LL ans = 0;
  46. for (int i = 1; i <= n; i++)
  47. scanf("%d", &a[i]);
  48. for (int i = 1; i < n; i++) {
  49. scanf("%d%d", &x, &y);
  50. add(x, y);
  51. add(y, x);
  52. }
  53. dfs(1, -1);
  54. sort(b + 1, b + 1 + n);
  55. cnt++;
  56. for (int i = 1; i <= cnt; i++) f[i] = i;
  57. for(int L = 1, R; L <= n; L = R + 1) {
  58. R = L;
  59. while(b[L].w == b[R + 1].w && R < n) R++;
  60. for (int i = L; i <= R; i++) {
  61. x = get(b[i].u), y = get(b[i].v);
  62. if(x != y) {
  63. v[b[i].id] = 1;
  64. sum++;
  65. }
  66. }
  67. for (int i = L; i <= R; i++) {
  68. x = get(b[i].u), y = get(b[i].v);
  69. if(x != y) {
  70. ans += b[i].w;
  71. // printf("%lld %d\n", ans, b[i].w);
  72. f[x] = y;
  73. }
  74. }
  75. }
  76. // printf("%lld %d\n", ans, sum);
  77. cout << ans << " " << sum << endl;
  78. for (int i = 1; i <= n; i++)
  79. if(v[i]) printf("%d ", i);
  80. }

  

Codeforces 1120D (树形DP 或 最小生成树)的更多相关文章

  1. Codeforces 1153D 树形DP

    题意:有一个游戏,规则如下:每个点有一个标号,为max或min, max是指这个点的值是所有子节点中值最大的那一个,min同理.问如何给这颗树的叶子节点赋值,可以让这棵树的根节点值最大. 思路:很明显 ...

  2. Codeforces 1088E 树形dp+思维

    比赛的时候看到题意没多想就放弃了.结果最后D也没做出来,还掉分了,所以还是题目做的太少,人太菜. 回到正题: 题意:一棵树,点带权值,然后求k个子连通块,使得k个连通块内所有的点权值相加作为分子除以k ...

  3. Codeforces 1179D 树形DP 斜率优化

    题意:给你一颗树,你可以在树上添加一条边,问添加一条边之后的简单路径最多有多少条?简单路径是指路径中的点只没有重复. 思路:添加一条边之后,树变成了基环树.容易发现,以基环上的点为根的子树的点中的简单 ...

  4. CodeForces - 337D 树形dp

    题意:一颗树上有且仅有一只恶魔,恶魔会污染距离它小于等于d的点,现在已经知道被污染的m个点,问恶魔在的可能结点的数量. 容易想到,要是一个点到(距离最远的两个点)的距离都小于等于d,那么这个点就有可能 ...

  5. CodeForces 219D 树形DP

    D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes i ...

  6. codeforces 337D 树形DP Book of Evil

    原题直通车:codeforces 337D Book of Evil 题意:一棵n个结点的树上可能存在一个Evil,Evil危险范围为d,即当某个点与它的距离x<=d时,那么x是危险的. 现已知 ...

  7. Up and Down the Tree CodeForces - 1065F (树形dp)

    链接 题目大意:给定$n$结点树, 假设当前在结点$v$, 有两种操作 $(1)$移动到$v$的子树内任意一个叶子上 $(2)$若$v$为叶子, 可以移动到距离$v$不超过$k$的祖先上 初始在结点$ ...

  8. codeforces 1053D 树形DP

    题意:给一颗树,1为根节点,有两种节点,min或者max,min节点的值是它的子节点的值中最小的,max节点的值是它的子节点的值中最大的,若共有k个叶子,叶子的值依次为1~k. 问给每个叶子的值赋为几 ...

  9. Codeforces 735E 树形DP

    题意:给你一棵树,你需要在这棵树上选择一些点染成黑色,要求染色之后树中任意节点到离它最近的黑色节点的距离不超过m,问满足这种条件的染色方案有多少种? 思路:设dp[x][i]为以x为根的子树中,离x点 ...

随机推荐

  1. 第2章 开始Flex

    * Flex开发中可用两种语言 1.MXML 2.ActionScript * Flex中使用两个组件集 1.MX (mx.*) 早期的Flex版本用到的组件集 2.Spark (spark.*) F ...

  2. Ubuntu命令:sudo、shutdown、apt-get、vim

    切换成ROOT用户: Ubuntu中默认不开启root账户,所以root账户是没有密码的, 但是会有一个非root的管理员账户,可以通过sudo来获得root权限,现在就可以用这个账户来设置密码 ** ...

  3. HDU - 233 Matrix

    原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5015 解题思路:一看到题目,感觉是杨辉三角形,然后用组合数学做,不过没想出来怎么做,后来看数据+递推思 ...

  4. YARN学习笔记——Overview and Architecture

    YARN的简介 什么是YARN MRv1的架构和缺陷 经典MapReduce的局限性 解决可伸缩性问题 YARN的架构 一个可运行任何分布式应用程序的集群 YARN中的应用程序提交 YARN的其他特性 ...

  5. [BZOJ5290][HNOI2018]道路

    bzoj luogu sol 考场上普及\(dp\)都做不来,果然是思想僵化了. 设\(f[u][i][j]\)表示在\(u\)点,上方有\(i\)条未修复的公路和\(j\)条未修复的铁路的最小花费. ...

  6. 如何在已经安装好的Nginx上增加新模块

    学习资源: https://blog.csdn.net/dxm2025/article/details/41149865 https://blog.csdn.net/qq_36663951/artic ...

  7. 根据当前日期算前一年、前一月、前一天(java基础)

    问题的本身没有什么难度,但是要想一下子找到一个现成的方法还真不是那么容易,本来以为java.util.Date中会有方法结果找了半天没找到,最后还是在Calendar中找到了,记下别忘了!! 核心:使 ...

  8. AngularJS:Http

    ylbtech-AngularJS:Http 1.返回顶部 1. AngularJS XMLHttpRequest $http 是 AngularJS 中的一个核心服务,用于读取远程服务器的数据. 使 ...

  9. php中的continue用法

    continue 2 表示跳出两层 continue 默认跳出一层 if (count($content_arr) > 0 ) { // 获取相应的goods数据 $goodsdata = ar ...

  10. 第三方引擎应用场景分析--Tokudb,infobright

    TokuDBTokuDB的特色:• Fractal Tree而不是B-Tree• 内部结点不仅有指向父子的指针还有Buffer区,数据写入先写buffer区,FIFO结构,写入只需要顺序添加到Buff ...