F. Roads in the Kingdom(树形dp)

题意:

给一张n个点n条边的无向带权图

定义不便利度为所有点对最短距离中的最大值

求出删一条边之后,保证图还连通时不便利度的最小值

$n <= 2e5 $

\(w_i <= 1e9\)

思路:树形dp

这个图是一个环上挂着很多颗树,首先把这个环处理出来,

删边只能在环上进行,所以可以先求出以环上每个点为根的树的直径和最大深度dep,

答案来源分为二种

  • 树内部两点最远距离 -> 直径 (树形dp 或者 两次bfs)
  • 两棵树深度最大的两点配对

假设环长度为\(k\),把环变成一个序列\(a_1,a_2,...,a_k\) 令\(a_0 = a_k\)

选择\(a_0\)做起点,用\(s_i\)表示第\(i\)个点到起点的距离

考虑每次断开的边为\(e(a_{i-1},a_i)\),那么答案分为三种情况

  • 序列\(1\)到\(i-1\)中选两个点配对取最大值
  • 序列\(i\)到\(k\)中选两个点配对取最大值
  • 前后各取一个点配对取最大值

计算第一种情况

假设取的两个点为\(1<=x<y<=i-1\),

则距离\(d = dep[x] + dep[y] + dis[x][y] = dep[x] - s[x] + dep[y] + s[y]\)

这样我们只需要顺序枚举维护\(dep[x] - s[x]\)的最大值即可

同理,第二种情况只需要逆序枚举维护\(dep[x] + s[x]\)的最大值即可

考虑第三种情况 假设取的点为\(1 <= x <= i - 1 , i <= y <= k\)

则距离\(d = dep[x] + dep[y] + dis[x][y] = dep[x] + dep[y] + s[k] - (s[y] - s[x])\)

$d = (dep[x] + s[k] + s[x]) + (dep[y] - s[y]) $

同理,顺序可算出第一部分最大值,逆序可以算出第二部分最大值

最后在删边后三种情况的最大值里取最小值再和树内部直径比较即可

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define P pair<int,int>
  4. #define ls(i) seg[i].lc
  5. #define rs(i) seg[i].rc
  6. using namespace std;
  7. const int N = 2e5 + 10;
  8. const LL inf = 1e18;
  9. int read(){
  10. int x = 0;
  11. char c = getchar();
  12. while(c < '0' || c > '9') c = getchar();
  13. while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
  14. return x;
  15. }
  16. vector<P>G[N];
  17. int n,k;
  18. int a[N],pa[N],e[N];
  19. LL s[N],dep[N],ans;
  20. void dfs(int u,int fa){
  21. pa[u] = fa;
  22. for(auto v:G[u]){
  23. if(v.first == fa) continue;
  24. if(pa[v.first] == 0) {
  25. e[v.first] = v.second;
  26. dfs(v.first,u);
  27. }
  28. else if(!k){
  29. int x = u;
  30. a[0] = v.first,s[1] = v.second;
  31. while(x != v.first) {
  32. a[++k] = x,s[k+1] = s[k] + e[x],x = pa[x];
  33. }
  34. a[++k] = v.first;
  35. }
  36. }
  37. }
  38. void dp(int u){
  39. pa[u] = 0;
  40. for(auto v:G[u]){
  41. if(pa[v.first] != 0){
  42. dp(v.first);
  43. ans = max(ans,dep[v.first] + v.second + dep[u]);
  44. dep[u] = max(dep[u], dep[v.first] + v.second);
  45. }
  46. }
  47. }
  48. LL sL[N],sR[N],L[N],R[N];///把环变成序列,断开的边左边配对,右边配对,左右配对的最大值
  49. int main(){
  50. int u,v,w;
  51. n = read();
  52. for(int i = 1;i <= n;i++){
  53. u = read(),v = read(),w = read();
  54. G[u].push_back(P(v,w));
  55. G[v].push_back(P(u,w));
  56. }
  57. k = 0;
  58. ans = 0;
  59. dfs(1,-1);
  60. for(int i = 1;i <= k;i++) pa[a[i]] = 0;
  61. for(int i = 1;i <= k;i++) dp(a[i]);
  62. LL mx = -inf;
  63. L[0] = sL[0] = -inf;
  64. for(int i = 1;i <= k;i++){
  65. sL[i] = max(sL[i-1],dep[a[i]] + s[i] + mx);
  66. L[i] = max(L[i-1],dep[a[i]] + s[k] + s[i]);
  67. mx = max(mx, dep[a[i]] - s[i]);
  68. }
  69. sR[k+1] = R[k+1] = mx = -inf;
  70. for(int i = k;i >= 1;i--){
  71. sR[i] = max(sR[i+1],dep[a[i]] - s[i] + mx);
  72. R[i] = max(R[i+1],dep[a[i]] - s[i]);
  73. mx = max(mx, dep[a[i]] + s[i]);
  74. }
  75. LL tmp = inf;
  76. for(int i = 1;i <= k;i++) tmp = min(tmp,max(L[i-1]+R[i],max(sL[i-1],sR[i])));
  77. cout<<max(ans,tmp)<<endl;
  78. return 0;
  79. }

Codeforces 835 F Roads in the Kingdom(树形dp)的更多相关文章

  1. Codeforces 835 F. Roads in the Kingdom

    \(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗 ...

  2. codeforces 427 div.2 F. Roads in the Kingdom

    F. Roads in the Kingdom time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  3. Codeforces 671D. Roads in Yusland(树形DP+线段树)

    调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...

  4. Codeforces Round #527 F - Tree with Maximum Cost /// 树形DP

    题目大意: 给定一棵树 每个点都有点权 每条边的长度都为1 树上一点到另一点的距离为最短路经过的边的长度总和 树上一点到另一点的花费为距离乘另一点的点权 选定一点出发 使得其他点到该点的花费总和是最大 ...

  5. Codeforces 1097G Vladislav and a Great Legend [树形DP,斯特林数]

    洛谷 Codeforces 这题真是妙的很. 通过看题解,终于知道了\(\sum_n f(n)^k​\)这种东西怎么算. update:经过思考,我对这题有了更深的理解,现将更新内容放在原题解下方. ...

  6. Codeforces 1606F - Tree Queries(虚树+树形 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 显然我们选择删除的点连同 \(u\) 会形成一个连通块,否则我们如果选择不删除不与 \(u\) 在同一连通块中的点,答案一定更优. 注意到 ...

  7. Codeforces 791D Bear and Tree Jump(树形DP)

    题目链接 Bear and Tree Jumps 考虑树形DP.$c(i, j)$表示$i$最少加上多少后能被$j$整除. 在这里我们要算出所有$c(i, k)$的和. 其中$i$代表每个点对的距离, ...

  8. codeforces 816 E. Karen and Supermarket(树形dp)

    题目链接:http://codeforces.com/contest/816/problem/E 题意:有n件商品,每件有价格ci,优惠券di,对于i>=2,使用di的条件为:xi的优惠券需要被 ...

  9. codeforces 161 D. Distance in Tree(树形dp)

    题目链接:http://codeforces.com/problemset/problem/161/D 题意:给出一个树,问树上点到点的距离为k的一共有几个. 一道简单的树形dp,算是一个基础题. 设 ...

随机推荐

  1. 《Linux就该这么学》,刘小伙实在人,给打个广告

    本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...

  2. C语言基础篇(一)关键字

    导航: 1. 数据类型 !!! 2. 自定义类型 !!!! 3. 逻辑结构 4. 类型修饰符 !! 5. 杂项 !! ----->x<------------->x<----- ...

  3. Codeforces Round #459 (Div. 2) D. MADMAX DFS+博弈

    D. MADMAX time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...

  4. 利用pandas和numpy计算表中每一列的均值

    import numpy as np import pandas as pd df = pd.DataFrame({'var1':np.random.rand(100), #生成100个0到1之间的随 ...

  5. POJ:3185-The Water Bowls(枚举反转)

    The Water Bowls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7402 Accepted: 2927 Descr ...

  6. POJ:3685-Matrix

    Matrix Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 7879 Accepted: 2374 Description Gi ...

  7. 使用dataframe解决spark TopN问题:分组、排序、取TopN和join相关问题

    package com.profile.mainimport org.apache.spark.sql.expressions.Windowimport org.apache.spark.sql.fu ...

  8. 理解线程3 c语言示例线程基本操作

    Table of Contents 1. 基本线程的动作 1.1. 设置线程属性 1.1.1. 设置脱离状态 1.1.2. 设置调度属性 1.2. 取消线程 1.3. 主线程创建多个线程示例 2. 了 ...

  9. APP遇到大量的真实手机号刷注册用户该如何应对?

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 在说如何应对之前,先给各位梳理移动端APP可能遇到哪些作弊风险.1. 渠道商刷量,伪造大量的下载量和装机量,但没有新用户注册:2. 对于电商.P2P ...

  10. 解决 ld: library not found for -lPods的问题

    现在打开有pods建好的workspace文件,尝试编译,会报ld: library not found for -lPods错误,原因就是工程里面的设置项覆盖了pods中xcconfig中的设置.解 ...