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]) $
同理,顺序可算出第一部分最大值,逆序可以算出第二部分最大值

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

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
#define ls(i) seg[i].lc
#define rs(i) seg[i].rc
using namespace std;
const int N = 2e5 + 10;
const LL inf = 1e18;
int read(){int x = 0;char c = getchar();while(c < '0' || c > '9') c = getchar();while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();return x;
}
vector<P>G[N];
int n,k;
int a[N],pa[N],e[N];
LL s[N],dep[N],ans;
void dfs(int u,int fa){pa[u] = fa;for(auto v:G[u]){if(v.first == fa) continue;if(pa[v.first] == 0) {e[v.first] = v.second;dfs(v.first,u);}else if(!k){int x = u;a[0] = v.first,s[1] = v.second;while(x != v.first) {a[++k] = x,s[k+1] = s[k] + e[x],x = pa[x];}a[++k] = v.first;}}
}
void dp(int u){pa[u] = 0;for(auto v:G[u]){if(pa[v.first] != 0){dp(v.first);ans = max(ans,dep[v.first] + v.second + dep[u]);dep[u] = max(dep[u], dep[v.first] + v.second);}}
}
LL sL[N],sR[N],L[N],R[N];///把环变成序列,断开的边左边配对,右边配对,左右配对的最大值
int main(){int u,v,w;n = read();for(int i = 1;i <= n;i++){u = read(),v = read(),w = read();G[u].push_back(P(v,w));G[v].push_back(P(u,w));}k = 0;ans = 0;dfs(1,-1);for(int i = 1;i <= k;i++) pa[a[i]] = 0;for(int i = 1;i <= k;i++) dp(a[i]);LL mx = -inf;L[0] = sL[0] = -inf;for(int i = 1;i <= k;i++){sL[i] = max(sL[i-1],dep[a[i]] + s[i] + mx);L[i] = max(L[i-1],dep[a[i]] + s[k] + s[i]);mx = max(mx, dep[a[i]] - s[i]);}sR[k+1] = R[k+1] = mx = -inf;for(int i = k;i >= 1;i--){sR[i] = max(sR[i+1],dep[a[i]] - s[i] + mx);R[i] = max(R[i+1],dep[a[i]] - s[i]);mx = max(mx, dep[a[i]] + s[i]);}LL tmp = inf;for(int i = 1;i <= k;i++) tmp = min(tmp,max(L[i-1]+R[i],max(sL[i-1],sR[i])));cout<<max(ans,tmp)<<endl;return 0;
}

转载于:https://www.cnblogs.com/jiachinzhao/p/7305578.html

Codeforces 835 F Roads in the Kingdom(树形dp)相关推荐

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

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

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

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

  3. [Codeforces 814D] An overnight dance in discotheque 树形dp,贪心

    题目链接 题解:这道题,首先可以发现,圆与圆关系只有内含与外离, 所以可以建立出一个树形结构, 每个圆的父亲是与这个圆半径相差最小且包含这个圆的圆, 这样,整个一张图形成了一个森林,可以将圆按半径排序 ...

  4. wannalfy 挑战赛8 F 白云的树(树形dp)

    链接:https://www.nowcoder.com/acm/contest/57/F 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言524288K 64b ...

  5. CodeForces - 1220E Tourism(边双缩点+树形dp)

    题目链接:点击查看 题目大意:给出一个由n个点和m条边构成的无向图,每个点都有一个权值,现在给出起点st,问从起点出发,如何规划路线可以使得途径的权值最大,唯一的约束是一条边不能连续经过,比如当前从u ...

  6. 【Christmas Game】【CodeCraft-21 and Codeforces Round #711 (Div. 2)】【Nim-博弈】【树形DP】【拆分树】

    CodeCraft-21 and Codeforces Round #711 (Div. 2) Christmas Game Nim-博弈 树形DP 拆分树 牛客链接 https://ac.nowco ...

  7. Codeforces 1088E Ehab and a component choosing problem(树形DP)

    Codeforces 1088E Ehab and a component choosing problem(树形DP) 题意 给一棵树,要求从中选一些联通分量,使得平均联通分量重量总和最大.如果有多 ...

  8. CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)

    CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换)   首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现.      第 ...

  9. CodeForces - 1324F Maximum White Subtree(树形dp)

    题目链接:点击查看 题目大意:给出 n 个点组成的树,每个点都有一个颜色,非黑即白,现在问对于每个点而言,选出一个连通块,使得白色点的个数与黑色点的个数做差最大 题目分析:记录一下div3的第一次ak ...

最新文章

  1. 哪位有方法把 dd/mm/yyyy的字符串 格式化成yyyy-mm-dd
  2. 快速排序,冒泡排序时间复杂度推导
  3. typescript 怎么表示当前时间减一个月_TypeScript类型元编程:实现8位数的算术运算...
  4. Adobe Flash Player(Flash播放器)下载地址
  5. 比尔盖茨的30条经典语录
  6. laravel graphql php,结合 Laravel 初步学习 GraphQL
  7. [css] 请你解释下什么是浮动和它的工作原理是什么?同时浮动会引起什么问题?
  8. poj 3071 Football
  9. mysql 协议的退出命令包及解析
  10. 安卓学习笔记29:使用SQLite数据库
  11. python怎样填充颜色_python – 使用颜色填充Tkinter画布对象之间的空间
  12. Metro UI 的设计感悟
  13. 74LS139改3―8线译码器_3、5号线沿线楼盘6800起!另:为无缝衔接地铁 新增调整公交线路一览!...
  14. Tensorflow 实战 Google 深度学习框架(第2版)---- 10.2.2节 P274 代码
  15. 如何用计算机计算胸围,胸围尺码换算(罩杯自动计算器)
  16. 房价与房租出现大幅“背离”?
  17. HTTP协议5之代理--转
  18. 二维码图片生成 hutool
  19. es6去除重复项_ES5 ES6中Array对象去除重复项的方法总结
  20. 【ArcGIS微课1000例】0053:注记(水平、沿直线、跟随要素、牵引线、弯曲注记)的创建与编辑

热门文章

  1. 车刀 matlab,可转位车刀的结构
  2. java反射对象赋值_Java反射详解
  3. 【Java学习笔记二】继承和多态
  4. #ifndef的作用
  5. Cow Contest——Floyed+连通性判断
  6. C++智能指针(一)智能指针的简单介绍
  7. C++经典问题:如果对象A中有对象成员B,对象B没有默认构造函数,那么对象A必须在初始化列表中初始化对象B?
  8. 【Linux系统编程学习】C库IO函数与系统IO函数的关系
  9. Makefile(一)
  10. 1066 图像过滤 (15 分)