4890: [Tjoi2017]城市

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 149  Solved: 91
[Submit][Status][Discuss]

Description

 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作。这个地区一共有ri座城市,《-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用。小明对这个地区深入研究后,觉得这个地区的交通费用太贵。小明想彻底改造这个地区,但是由于上司给他的资源有限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高速公路(即交通费用一样),使得这个地区的两个城市之间的最大交通费用最小(即使得交通费用最大的两座城市之间的交通费用最小),并且保证修建完之后任意两座城市相互可达。如果你是小明,你怎么解决这个问题?

Input

输入数据的第一行为一个整数n,代表城市个数。

接下来的n - 1行分别代表了最初的n-1条公路情况。每一行都有三个整数u,v,d。u,v代表这条公路的两端城市标号,d代表这条公路的交通费用。

Output

 输出数据仅有一行,一个整数,表示进行了最优的改造之后,该地区两城市 之间最大交通费用。

Sample Input

5
1 2 1
2 3 2
3 4 3
4 5 4

Sample Output

 7

HINT

对于30%的数据,1<=n<500

对于100%的数据,1<=n<=5000

1 <= u,v <= n,1<= d <= 2000

  1. /*
  2. 要想删一条边再添一条边使一棵树中两点间最大距离最小
  3. 容易想到跟树的直径有关
  4. N比较小,可以枚举要删那一条边。删掉(u,v)之后树就成了两个联通块。
  5. 如果树的直径没变,对答案没有影响。 可以求出联通块1,2的直径。
  6. (所以可以只枚举删直径上的边,但我没有...)
  7. 那么问题就转化为在1,2联通块内分别找一个点使它到联通块内最远的点距离最近。
  8. 这个距离就是树的半径。然后把这两个点连起来即可。
  9. 如何维护半径?
  10. 求直径时需要求出每个点为起点的最长链和次长链
  11. 考虑距离它最远的那个点,在它的子树内还是子树外
  12. 子树内:最长链
  13. 子树外:dfs维护这个点子树外的最长链
  14. 如何维护一个点子树外的最长链?
  15. 当dfs到一个x时,对于x和他的父亲y,若x不在y的最长链内,那么ans[x](x到子树外最远距离)为max(y最长链+dis[x][y],ans[y]+dis[x][y])
  16. 否则ans[x]为max(y的次长链+dis[x][y],ans[y]+dis[x][y])
  17. 最后对每种情况答案取min即可。
  18. */
  19. #include<bits/stdc++.h>
  20.  
  21. #define N 5007
  22. #define inf 0x3f3f3f3f
  23.  
  24. using namespace std;
  25. int n,m,ans,cnt,dis,res;
  26. int head[N<<],mv[N],u[N],v[N],w[N];
  27. int dp[N][];
  28. bool vis[N];
  29. struct edge{
  30. int u,v,w,nxt;
  31. }e[N<<];
  32.  
  33. inline void add(int u,int v,int w)
  34. {
  35. e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;
  36. }
  37.  
  38. inline int read()
  39. {
  40. int x=,f=;char c=getchar();
  41. while(c>''||c<''){if(c=='-')f=-;c=getchar();}
  42. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  43. return x*f;
  44. }
  45.  
  46. void getd(int u)
  47. {
  48. for(int i=head[u];i;i=e[i].nxt)
  49. {
  50. int v=e[i].v;
  51. if(vis[v]) continue;
  52. vis[v]=;getd(v);
  53. if(dp[u][]<dp[v][]+e[i].w)
  54. {
  55. dp[u][]=dp[u][];mv[u]=v;
  56. dp[u][]=dp[v][]+e[i].w;
  57. }
  58. else if(dp[u][]<dp[v][]+e[i].w)
  59. dp[u][]=dp[v][]+e[i].w;
  60. }dis=max(dis,dp[u][]+dp[u][]);
  61. }
  62.  
  63. void getr(int u,int from)
  64. {
  65. res=min(res,max(from,dp[u][]));
  66. for(int i=head[u];i;i=e[i].nxt)
  67. {
  68. int v=e[i].v;
  69. if(!vis[v]) continue;
  70. vis[v]=;
  71. if(mv[u]==v)
  72. getr(v,max(dp[u][]+e[i].w,from+e[i].w));
  73. else
  74. getr(v,max(dp[u][]+e[i].w,from+e[i].w));
  75.  
  76. }
  77. }
  78.  
  79. void clear()
  80. {
  81. memset(dp,,sizeof dp);
  82. memset(mv,,sizeof mv);
  83. memset(vis,,sizeof vis);
  84. res=inf;dis=;
  85. }
  86.  
  87. int main()
  88. {
  89. n=read();
  90. for(int i=;i<n;i++)
  91. {
  92. u[i]=read();v[i]=read();w[i]=read();
  93. add(u[i],v[i],w[i]);add(v[i],u[i],w[i]);
  94. }
  95. int d1,d2,r1,r2;ans=res=inf;dis=;
  96. for(int i=;i<n;i++)
  97. {
  98. vis[v[i]]=;getd(u[i]); d1=dis;
  99. dis=;getd(v[i]); d2=dis;
  100. //联通块1,2的直径
  101. vis[v[i]]=;getr(u[i],); r1=res;
  102. res=inf;getr(v[i],); r2=res;
  103. //联通块1,2的半径
  104. ans=min(ans,max(max(d1,d2),r1+r2+w[i]));
  105. clear();
  106. }
  107. printf("%d\n",ans);
  108. return ;
  109. }

bzoj4890[Tjoi2017]城市(树的半径)的更多相关文章

  1. BZOJ4890 Tjoi2017城市

    显然删掉的边肯定是直径上的边.考虑枚举删哪一条.然后考虑怎么连.显然新边应该满足其两端点在各自树中作为根能使树深度最小.只要线性求出这个东西就可以了,这与求树的重心的过程类似. #include< ...

  2. [BZOJ4890][TJOI2017]城市(DP)

    题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收 ...

  3. BZOJ4890 [Tjoi2017]城市 【树形dp】

    题目链接 BZOJ4890 题解 枚举断开哪一条边,然后对剩余的两棵树分别做一遍换根法树形dp 需要求出每个点到树中其它点距离的最大值\(f[i]\)和次大值\(g[i]\)[用以辅助换根计算最大值] ...

  4. [TJOI2017] 城市 (树的直径,贪心)

    题目链接 Solution 这道题,调了我一晚上... 一直80分 >_<|| ... 考虑到几点: 分开任意一条边 \(u\) ,那么其肯定会断成两棵树. 肯定是分开直径上的边最优,否则 ...

  5. luogu P3761 [TJOI2017]城市 树的直径 bfs

    LINK:城市 谢邀,学弟说的一道毒瘤题. 没有真正的省选题目毒瘤 或者说 写O(n)的做法确实毒瘤. 这里给一个花20min就写完的非常好写的暴力. 容易想到枚举哪条边删掉 删掉之后考虑在哪两个点上 ...

  6. 【BZOJ4890】[TJOI2017]城市(动态规划)

    [BZOJ4890][TJOI2017]城市(动态规划) 题面 BZOJ 洛谷 题解 数据范围都这样了,显然可以暴力枚举断开哪条边. 然后求出两侧直径,暴力在直径上面找到一个点,使得其距离直径两端点的 ...

  7. [TJOI2017]城市(树的直径)

    [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达, ...

  8. 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市

    P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...

  9. [TJOI2017]城市 【树的直径+暴力+优化】

    Online Judge:Luogu P3761 Label:树的直径,暴力 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有n座城市,n-1条高速公路,保证了 ...

随机推荐

  1. ajax导出excel文件并增加等待动画效果

    html: <button class="btn btn-default" onclick="logToExcel('{:url('userLogToExcel', ...

  2. HDU 2280 状压DP

    用dfs找到状态的最优解 且那个正方形块可以由两个水平块组成,所以无需考虑 #include <cstdio> #include <cstring> #include < ...

  3. [bzoj3630][JLOI2014]镜面通道_计算几何_网络流_最小割

    镜面通道 bzoj-3630 JLOI-2014 题目大意:题目链接. 注释:略. 想法: 我们发现,只要上下界没有被完全封死,我们就一定有一条合法的光路. 所以只需要将上界和下界拆开即可. 拆点,把 ...

  4. 洛谷 P1608 路径统计

    P1608 路径统计 题目描述 “RP餐厅”的员工素质就是不一般,在齐刷刷的算出同一个电话号码之后,就准备让HZH,TZY去送快餐了,他们将自己居住的城市画了一张地图,已知在他们的地图上,有N个地方, ...

  5. HDU 5074 Hatsune Miku 2014 Asia AnShan Regional Contest dp(水

    简单dp #include <stdio.h> #include <cstring> #include <iostream> #include <map> ...

  6. Java设计模式—单例设计模式(Singleton Pattern)全然解析

    转载请注明出处:http://blog.csdn.net/dmk877/article/details/50311791 相信大家都知道设计模式,听的最多的也应该是单例设计模式,这种模式也是在开发中用 ...

  7. Redis学习笔记3-Redis5个可运行程序命令的使用

    在redis安装文章中,说到安装好redis后,在/usr/local/bin下有5个关于redis的可运行程序.以下关于这5个可运行程序命令的具体说明. redis-server Redisserv ...

  8. Hiho1041 国庆出游 搜索题解

    题目3 : 国庆出游 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比較有特色:它共同拥有n座城市(编号1-n): ...

  9. spring mvc +Mybatis3.1 整合的时候异常

    在使用Mybatis3.10+spring3.10+mybatis-spring-1.0.0集成,使用spring 时发生例如以下错误: 严重: Servlet.service() for servl ...

  10. java 翻页工具类

    Pagination类 package com.paic.bics.core.mybatis.page; import java.util.List; @SuppressWarnings(" ...