BZOJ_3124_[Sdoi2013]直径_树形DP

Description

小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)
表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。 
 直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。
现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。

Input

第一行包含一个整数N,表示节点数。
接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c
的无向边。

Output

共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有
直径经过的边的数量。

Sample Input

6
3 1 1000
1 4 10
4 2 100
4 5 50
4 6 100

Sample Output

1110
2

【样例说明】
直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。

HINT

对于100%的测试数据:2≤N≤200000,所有点的编号都在1..N的范围内,
边的权值≤10^9。


边权非负,可以用一个基于贪心的方法求直径。

以1为根进行dfs,求出每个点到根的距离dis1,令rt1为最大的一个点。

以rt1为根就能拽出来一条直径rt1---rt2,求出每个点到根的距离dis2。

所求的那些边一定是连续的,如果不连续则中间的那个一定可以替代边上的边。

考虑dis2[i]=dis2[rt2]的那些点i,一定可以和rt1形成又一条直径,于是可以把i和rt2的lca一下的那些边抠掉。

然后反过来再做一遍就可以啦。

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. #define N 200050
  6. typedef long long ll;
  7. int head[N],to[N<<1],nxt[N<<1],val[N<<1],cnt,n,fa[N],dep[N],f[25][N],dis3[N];
  8. ll dis1[N],dis2[N];
  9. int rt1,rt2;
  10. inline void add(int u,int v,int w) {
  11. to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
  12. }
  13. void dfs1(int x,int y) {
  14. int i;
  15. if(dis1[x]>dis1[rt1]) rt1=x;
  16. for(i=head[x];i;i=nxt[i]) {
  17. if(to[i]!=y) {
  18. dis1[to[i]]=dis1[x]+val[i];
  19. dfs1(to[i],x);
  20. }
  21. }
  22. }
  23. void dfs2(int x,int y) {
  24. int i; fa[x]=y; f[0][x]=y;
  25. if(dis2[x]>dis2[rt2]) rt2=x;
  26. for(i=head[x];i;i=nxt[i]) {
  27. if(to[i]!=y) {
  28. dep[to[i]]=dep[x]+1;
  29. dis2[to[i]]=dis2[x]+val[i];
  30. dfs2(to[i],x);
  31. }
  32. }
  33. }
  34. int lca(int x,int y) {
  35. if(dep[x]<dep[y]) swap(x,y);
  36. int i;
  37. for(i=20;i>=0;i--) {
  38. if(f[i][x]&&dep[f[i][x]]>=dep[y]) x=f[i][x];
  39. }
  40. if(x==y) return x;
  41. for(i=20;i>=0;i--) {
  42. if(f[i][x]&&f[i][y]&&f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y];
  43. }
  44. return f[0][x];
  45. }
  46. void dfs3(int x,int y) {
  47. int i; f[0][x]=y;
  48. for(i=head[x];i;i=nxt[i]) {
  49. if(to[i]!=y) {
  50. dep[to[i]]=dep[x]+1;
  51. dis3[to[i]]=dis3[x]+val[i];
  52. dfs3(to[i],x);
  53. }
  54. }
  55. }
  56. int main() {
  57. scanf("%d",&n);
  58. int i,x,y,z;
  59. for(i=1;i<n;i++) {
  60. scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z);
  61. }
  62. dfs1(1,0);
  63.  
  64. dfs2(rt1,0);
  65. int j;
  66. for(i=1;(1<<i)<=n;i++) {
  67. for(j=1;j<=n;j++) f[i][j]=f[i-1][f[i-1][j]];
  68. }
  69. int U=rt2;
  70. for(i=1;i<=n;i++) if(dis2[i]==dis2[rt2]) U=lca(U,i);
  71. memset(f,0,sizeof(f));
  72. dfs3(rt2,0);
  73. for(i=1;(1<<i)<=n;i++) {
  74. for(j=1;j<=n;j++) f[i][j]=f[i-1][f[i-1][j]];
  75. }
  76. int D=rt1;
  77. // printf("%d %d\n",rt1,rt2);
  78. for(i=1;i<=n;i++) if(dis3[i]==dis3[rt1]) D=lca(D,i);
  79. printf("%lld\n%d\n",dis2[rt2],dep[D]-dep[U]);
  80. }

BZOJ_3124_[Sdoi2013]直径_树形DP的更多相关文章

  1. 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)

    传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...

  2. BZOJ_1864_[Zjoi2006]三色二叉树_树形DP

    BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...

  3. BZOJ_3573_[Hnoi2014]米特运输_树形DP+hash

    BZOJ_3573_[Hnoi2014]米特运输_树形DP+hash 题意: 给你一棵树每个点有一个权值,要求修改最少的权值,使得每个节点的权值等于其儿子的权值和且儿子的权值都相等. 分析: 首先我们 ...

  4. B20J_4027_[HEOI2015]兔子与樱花_树形DP

    B20J_4027_[HEOI2015]兔子与樱花_树形DP 题意: 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编 ...

  5. BZOJ_1040_[ZJOI2008]骑士_树形DP

    BZOJ_1040_[ZJOI2008]骑士_树形DP 题意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各 界的赞扬.最近发生了一件可怕的事情,邪 ...

  6. BZOJ_1060_时态同步_树形DP

    BZOJ_1060_时态同步_树形DP 题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1060 分析:水水的树形DP. 用儿子的最大值更新父亲, ...

  7. BZOJ_1827_[Usaco2010 Mar]gather 奶牛大集会_树形DP

    BZOJ_1827_[Usaco2010 Mar]gather 奶牛大集会_树形DP 题意:Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会.当然,她会选择最方便的地点来 ...

  8. BZOJ_4726_[POI2017]Sabota?_树形DP

    BZOJ_4726_[POI2017]Sabota?_树形DP Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属 ...

  9. BZOJ_1304_[CQOI2009]叶子的染色_树形DP

    BZOJ_1304_[CQOI2009]叶子的染色_树形DP Description 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白 ...

随机推荐

  1. Atom 编辑器使用和学习

    事先准备:下载 Github 开源文本编辑器 Atom,并安装Atom 官网 | 搜索 “Atom下载” 常用快捷键:http://blog.csdn.net/hunyxv/article/detai ...

  2. Lua学习九----------Lua字符串

    © 版权声明:本文为博主原创文章,转载请注明出处 1.Lua字符串 - ''单引号间的一串字符 - ""双引号之间的一串字符 - [[]]之间的一串字符 2.Lua转义字符 3.字 ...

  3. ubuntu16.04--在标题栏显示网速

    有时感觉网络失去响应,就通过Ubuntu 14.04自带的系统监视器程序来查看当前网速,但是这样很不方便,遂打算让网速显示在标题栏,那样就随时可直观的看到.一番搜索尝试后,成功实现!同时也实现了CPU ...

  4. java从apk文件获取包名、版本号、icon

    依赖:仅依赖aapt.exe 支持:仅限windows 功能:用纯java获取apk文集里的包名,版本号,图标文件[可获取到流直接保存到文件系统] 原理:比较上一篇文章里通过反编译然后解析Androi ...

  5. ubantu 彻底卸载mysql

    卸载mysql 第一步 1 sudo apt-get autoremove --purge mysql-server-5.0 2 sudo apt-get remove mysql-server 3 ...

  6. HDFS源码分析DataXceiver之整体流程

    在<HDFS源码分析之DataXceiverServer>一文中,我们了解到在DataNode中,有一个后台工作的线程DataXceiverServer.它被用于接收来自客户端或其他数据节 ...

  7. LeetCode108_Convert SortedArray to BinarySearchTree(将有序数组转成二叉排序树) Java题解

    题目: Given an array where elements are sorted in ascending order, convert it to a height balanced BST ...

  8. 1-3:CSS3课程入门之伪类和伪元素

    E:target 表示当前的URL片段的元素类型,这个元素必须是E E:disabled 表示不可点击的表单控件 E:enabled 表示可点击的表单控件 E:checked 表示已选中的checkb ...

  9. python 基础 5.3 类的重写

    一. 类的重写 只需要重新定义类的属性(变量),就是累的重写了 示例:重新定义类grandson的 name属性   #/usr/bin/python #coding=utf-8 #@Time :20 ...

  10. MySQL重置root用户密码的方法【亲测可用】

    1. 报错截图 2.当确认已经忘记MySQL密码,则可以通过以下方案重置root用户密码.双击打开C:\Program Files\MySQL\MySQL Server 5.1\my.ini文件,如下 ...