题意:给你一颗树,你可以把这棵树上的一条边的边权变为0,现在让你选一个根,让所有点到这个点的最大距离尽量的小。如果有多个根的最大距离距离相同,输出编号最小的边。

思路:如果没有把边权变为0的操作,这个题实际上是找树的直径的中心。现在有变为0的操作,很容易想到加一维来标记是否已经把某条边的边权变为0。我们不妨先算出以1为根的答案。设dp[i][0]是以i为根的子树中没有变边权的最大距离,dp[i][1]是把最长的那条路径的某条边边权变为0后的这条最长路径长度的最小值。我们发现只知道最长的路径好像不够,因为最长路径的某条边边权变为0后可能就没次长路径长了。所以我们需要维护一下次长路径。那么我们在第一遍dfs的时候维需要护一下以i为根的子树中的最长路径和次长路径,以及最长路径和次长路径在修改后的最小长度。对于不带修改的最长路径和次长路径,直接维护就行。那么怎么维护修改过的最长路径的最小长度呢?我们需要记录一下到点i的最长路径中和i相邻的点j(j是i的孩子),那么分两种情况:1:把i和j之间的边删除。2:取之前删过的边的最小值加上i和j点之间的边的边权。设dp[i][0][1]为以i为根的最长路径(0:最长, 1:次长)(1:带修改, 0:不修改)的最小长度,那么dp[i][0][1] = min(dp[j][0][0], max(dp[j][0][1], dp[j][1][0]) + w)。次长路同理可得。那么我们就可以得出以1为根的答案了。ans = min(dp[1][0][1], dp[1][1][0])。现在考虑用换根法计算以其它点为根的答案,即来自父节点方向的答案的贡献。我们考虑一下父节点对我们的影响。设f[i][0/1]为以i为根它的父亲节点方向所形成的路径的的最大长度(带修改/不带修改),那么我们在计算以i为根的答案时把父节点方向的贡献也考虑在内就行,即考虑是修改i和父节点连的边,还是修改父节点方向的边,还是修改子树的边?这样就把答案计算出来了。怎么维护f[i][0]和f[i][1]呢?f[i][0]肯定来源于i的父节点方向最长距离和父节点的子树的最长距离取max再加上i和父节点的边权。子树的最长距离是不包括i的,所以我们转移的时候要特判一下。那么问题来了,我们的次长距离万一就是点i怎么办?所以我们之前相当于少维护了个第三长的距离,即第一遍dfs时需要维护最长,次长,第三长的距离。f[i][1]也一样,考虑枚举修改的哪条边来进行转移(父节点方向的边,子树方向的边)。

代码:

  1. #include <bits/stdc++.h>
  2. #define pii pair<int, int>
  3. using namespace std;
  4. const int maxn = 200010;
  5. pii dp[maxn][3][2];//点, 第几远,不删边/删边
  6. int f[maxn][2];//父亲节点来的,不删边/删边
  7. int d[maxn];
  8. vector<pii> G[maxn];
  9. int ans, pos;
  10. void add(int x, int y, int z) {
  11. G[x].push_back(make_pair(y, z));
  12. G[y].push_back(make_pair(x, z));
  13. }
  14. void dfs1(int x, int fa) {
  15. for (auto y : G[x]) {
  16. if(y.first == fa) continue;
  17. dfs1(y.first, x);
  18. d[y.first] = y.second;
  19. if(dp[y.first][0][0].first + y.second >= dp[x][0][0].first) {
  20. dp[x][2][0] = dp[x][1][0];
  21. dp[x][1][0] = dp[x][0][0];
  22. dp[x][0][0] = make_pair(dp[y.first][0][0].first + y.second, y.first);
  23. } else if(dp[y.first][0][0].first + y.second >= dp[x][1][0].first) {
  24. dp[x][2][0] = dp[x][1][0];
  25. dp[x][1][0] = make_pair(dp[y.first][0][0].first + y.second, y.first);
  26. } else if(dp[y.first][0][0].first + y.second >= dp[x][2][0].first) {
  27. dp[x][2][0] = make_pair(dp[y.first][0][0].first + y.second, y.first);
  28. }
  29. }
  30. int tmp = dp[x][0][0].second;
  31. dp[x][0][1].first = min(dp[tmp][0][0].first, max(dp[tmp][0][1].first, dp[tmp][1][0].first) + d[tmp]);
  32. tmp = dp[x][1][0].second;
  33. dp[x][1][1].first = min(dp[tmp][0][0].first, max(dp[tmp][0][1].first, dp[tmp][1][0].first) + d[tmp]);
  34. }
  35. void dfs2(int x, int fa) {
  36. int tmp = min(max(f[x][0], max(dp[x][0][1].first, dp[x][1][0].first)), max(f[x][1], dp[x][0][0].first));
  37. if(tmp < ans) {
  38. ans = tmp;
  39. pos = x;
  40. } else if(tmp == ans) {
  41. pos = min(pos, x);
  42. }
  43. for (auto y : G[x]) {
  44. if(y.first == fa) continue;
  45. if(y.first == dp[x][0][0].second) {
  46. f[y.first][0] = max(dp[x][1][0].first, f[x][0]) + y.second;
  47. f[y.first][1] = min(max(dp[x][1][0].first, f[x][0]), min(max(f[x][0], max(dp[x][1][1].first, dp[x][2][0].first)), max(dp[x][1][0].first, f[x][1])) + y.second);
  48. } else {
  49. f[y.first][0] = max(dp[x][0][0].first, f[x][0]) + y.second;
  50. if(dp[x][1][0].second == y.first) {
  51. f[y.first][1] = min(max(dp[x][0][0].first, f[x][0]), min(max(f[x][0], max(dp[x][0][1].first, dp[x][2][0].first)), max(dp[x][0][0].first, f[x][1])) + y.second);
  52. } else {
  53. f[y.first][1] = min(max(dp[x][0][0].first, f[x][0]), min(max(f[x][0], max(dp[x][0][1].first, dp[x][1][0].first)), max(dp[x][0][0].first, f[x][1])) + y.second);
  54. }
  55. }
  56. dfs2(y.first, x);
  57. }
  58. }
  59. int main() {
  60. int T, n, u, v, w;
  61. // freopen("in.txt", "r", stdin);
  62. // freopen("out.txt", "w", stdout);
  63. scanf("%d", &T);
  64. while(T--) {
  65. scanf("%d", &n);
  66. for (int i = 1; i <= n; i++) {
  67. G[i].clear();
  68. memset(dp[i], 0, sizeof(dp[i]));
  69. memset(f[i], 0, sizeof(f[i]));
  70. d[i] = 0;
  71. }
  72. for (int i = 1; i < n; i++) {
  73. scanf("%d%d%d", &u, &v, &w);
  74. add(u, v, w);
  75. }
  76. dfs1(1, 0);
  77. ans = max(dp[1][0][1].first, dp[1][1][0].first);
  78. pos = 1;
  79. dfs2(1, 0);
  80. printf("%d %d\n", pos, ans);
  81. }
  82. }

  

HDU 6613 Squrirrel 树形dp的更多相关文章

  1. HDU 2196.Computer 树形dp 树的直径

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  2. HDU 2196 Computer 树形DP经典题

    链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问 ...

  3. hdu 6201 【树形dp||SPFA最长路】

    http://acm.hdu.edu.cn/showproblem.php?pid=6201 n个城市都在卖一种书,该书的价格在i城市为cost[i],商人打算从某个城市出发到另一个城市结束,途中可以 ...

  4. HDU 2196 Computer 树形DP 经典题

    给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权, ...

  5. hdu 4081 最小生成树+树形dp

    思路:直接先求一下最小生成树,然后用树形dp来求最优值.也就是两遍dfs. #include<iostream> #include<algorithm> #include< ...

  6. HDU 3899 简单树形DP

    题意:一棵树,给出每个点的权值和每条边的长度, 点j到点i的代价为点j的权值乘以连接i和j的边的长度.求点x使得所有点到点x的代价最小,输出 虽然还是不太懂树形DP是什么意思,先把代码贴出来把. 这道 ...

  7. HDU 4714 Tree2cycle (树形DP)

    题意:给定一棵树,断开一条边或者接上一条边都要花费 1,问你花费最少把这棵树就成一个环. 析:树形DP,想一想,要想把一棵树变成一个环,那么就要把一些枝枝叶叶都换掉,对于一个分叉是大于等于2的我们一定 ...

  8. hdu Anniversary party 树形DP,点带有值。求MAX

    Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  9. HDU 4313 Matrix 树形dp

    题意: 给定n个点的树,m个黑点 以下n-1行给出边和删除这条边的费用 以下m个黑点的点标[0,n-1] 删除一些边使得随意2个黑点都不连通. 问删除的最小花费. 思路: 树形dp 每一个点有2个状态 ...

随机推荐

  1. 阿里HBase的数据管道设施实践与演进

    摘要:第九届中国数据库技术大会,阿里巴巴技术专家孟庆义对阿里HBase的数据管道设施实践与演进进行了讲解.主要从数据导入场景. HBase Bulkload功能.HImporter系统.数据导出场景. ...

  2. Django2 + ORM 做一个简单的登陆

    . ├── db.sqlite3 ├── manage.py ├── myormLogin │   ├── __init__.py │   ├── __pycache__ │   │   ├── __ ...

  3. Python_004(列表和元组)

    一.列表 1. 列表: 列表的创建:li = [],列表中可以放置字符串,元组,列表,字典,列表等各种数据类型,32位的Python可以存放2^32个数据 2. 列表的索引和切片 列表的索引:格式ls ...

  4. 【转】django 正则URL 匹配

    django 正则URL 匹配  转自:https://www.cnblogs.com/chenkeven/articles/9305260.html 一.引子 在day17 作业中,我们查看主机详细 ...

  5. Flask学习 1创建第一个页面

    #!/usr/bin/env python # encoding: utf-8 """ @version: v1.0 @author: cxa @file: hello. ...

  6. EZOJ #386 最小生成树

    分析 先建出最小生成树 之后每次倍增找环即可 代码 #include<bits/stdc++.h> using namespace std; #define int long long s ...

  7. 牛客提高D2t1 ACGT

    分析 用map维护一下每种字符串当前有几个即可 代码 #include<iostream> #include<cstdio> #include<cstring> # ...

  8. 建站手册-template

    ylbtech-建站手册: 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbtech.cn ...

  9. Centos7.2命令安装图形化界面

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/liang_operations/arti ...

  10. Vagrant 手册之 Vagrantfile - 机器设置 config.vm

    原文地址 配置的命名空间:config.vm config.vm 中的设置修改 Vagrant 管理的机器的配置. 1. 可用的设置项 config.vm.boot_timeout Vagrant 等 ...