Codeforces 835F Roads in the Kingdom (环套树 + DP)
题目链接 Roads in the Kingdom
题意 给出一个环套树的结构,现在要删去这个结构中的一条边,满足所有点依然连通。
删边之后的这个结构是一棵树,求所有删边情况中树的直径的最小值。
显然能被删掉的边是环上的边。
首先预处理出这个环。环上的每一个点都是一棵树的根。
假设环上有$cnt$个点,首先我们要求出这$cnt$棵树的树的直径的最大值$ret$。
然后我们要求出这$cnt$棵树的最大深度$deep[i]$。
接下来我们就只考虑环上的点了。
设$fl[i]$为从环上的$1$号点开始往右走,走到$i$或之前的某一棵子树的路径长度最大值。
设$fr[i]$为从环上的$n$号点开始往左走,走到$i$或之后的某一棵子树的路径长度最大值。
设$cl[i]$为从左边开始往右走走到环上的第$i$的点停止不动的时候经过的路径长度最大值。
设$cr[i]$为从右边开始往左走走到环上的第$i$的点停止不动的时候经过的路径长度最大值。
设$gl[i]$为起点终点都在$i$点或之前能经过的路径长度最大值。(起点终点可能在某个子树中)
设$gr[i]$为起点终点都在$i$点或之后能经过的路径长度最大值。
做一遍$DP$即可。
- #include <bits/stdc++.h>
- using namespace std;
- #define rep(i, a, b) for (int i(a); i <= (b); ++i)
- #define dec(i, a, b) for (int i(a); i >= (b); --i)
- #define MP make_pair
- #define fi first
- #define se second
- typedef long long LL;
- typedef pair <int, LL> PII;
- const int N = 2e5 + 10;
- vector <PII> v[N];
- vector <int> c;
- int isroot[N], a[N], father[N], vis[N], cnt = 0, n;
- int cnt_node;
- LL now_dis, ans, ret;
- LL val[N], deep[N], pre[N], suc[N], fl[N], fr[N], cl[N], cr[N], gl[N], gr[N];
- map <pair <int, int>, LL > mp;
- int get_circle(int x){
- vis[x] = 1;
- for (auto now : v[x]){
- int u = now.fi;
- if (u == father[x]) continue;
- father[u] = x;
- if (vis[u]){
- cnt = 0;
- int w = x;
- while (w ^ u){
- a[++cnt] = w;
- isroot[w] = cnt;
- w = father[w];
- }
- a[++cnt] = u;
- isroot[u] = cnt;
- return 1;
- }
- if (get_circle(u)) return 1;
- }
- return 0;
- }
- void dfs(int node, int x, int fa, LL dep){
- if (dep > deep[node]){
- cnt_node = x;
- deep[node] = dep;
- }
- for (auto now : v[x]){
- int u = now.fi;
- if (u == fa) continue;
- if (isroot[u]) continue;
- dfs(node, u, x, dep + now.se);
- }
- }
- void dfs2(int x, int fa, int extra, LL dep){
- now_dis = max(now_dis, dep);
- for (auto now : v[x]){
- int u = now.fi;
- if ((u == fa) || (isroot[u] && u != extra)) continue;
- dfs2(u, x, extra, dep + now.se);
- }
- }
- int main(){
- scanf("%d", &n);
- rep(i, 1, n){
- int x, y;
- LL z;
- scanf("%d%d%lld", &x, &y, &z);
- v[x].push_back(MP(y, z));
- v[y].push_back(MP(x, z));
- mp[MP(x, y)] = mp[MP(y, x)] = z;
- }
- father[1] = 0;
- get_circle(1);
- rep(i, 1, cnt){
- cnt_node = 0;
- dfs(i, a[i], 0, 0);
- if (deep[i] > 0){
- now_dis = 0;
- dfs2(cnt_node, 0, a[i], 0);
- ret = max(ret, now_dis);
- }
- }
- val[0] = mp[MP(a[1], a[cnt])];
- rep(i, 1, cnt - 1) val[i] = mp[MP(a[i], a[i + 1])];
- pre[1] = 0; rep(i, 2, cnt) pre[i] = pre[i - 1] + val[i - 1];
- suc[cnt] = 0; dec(i, cnt - 1, 1) suc[i] = suc[i + 1] + val[i];
- fl[1] = deep[1]; rep(i, 2, n) fl[i] = max(fl[i - 1], pre[i] + deep[i]);
- fr[cnt] = deep[cnt]; dec(i, n - 1, 1) fr[i] = max(fr[i + 1], suc[i] + deep[i]);
- cl[1] = 0; cl[2] = deep[1] + val[1];
- rep(i, 3, cnt) cl[i] = max(cl[i - 1], deep[i - 1]) + val[i - 1];
- cr[cnt] = 0, cr[cnt - 1] = deep[cnt] + val[cnt - 1];
- dec(i, cnt - 2, 1) cr[i] = max(cr[i + 1], deep[i + 1]) + val[i];
- rep(i, 2, cnt) gl[i] = max(gl[i - 1], cl[i] + deep[i]);
- dec(i, cnt - 1, 1) gr[i] = max(gr[i + 1], cr[i] + deep[i]);
- ans = gl[cnt];
- rep(i, 1, cnt - 1) ans = min(ans, max(fl[i] + fr[i + 1] + val[0], max(gl[i], gr[i + 1])));
- ans = max(ans, ret);
- printf("%lld\n", ans);
- return 0;
- }
Codeforces 835F Roads in the Kingdom (环套树 + DP)的更多相关文章
- Codeforces 835F Roads in the Kingdom - 动态规划
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗基环树,要求删去其中一条边,使得剩下的图形是一棵树,并且最长路的长度最短,求最长路的最短长度. 路径可以分为两部分:跨过环 和 在树内 ...
- 【BZOJ】1040: [ZJOI2008]骑士 环套树DP
[题意]给定n个人的ai和bi,表示第i个人能力值为ai且不能和bi同时选择,求能力值和最大的选择方案.n<=10^6. [算法]环套树DP(基环树) [题解]n个点n条边——基环森林(若干环套 ...
- 【距离GDKOI:44天&GDOI:107天】【BZOJ1040】[ZJOI2008] 骑士 (环套树DP)
其实已经准备退役了,但GDOI之前还是会继续学下去的!!当成兴趣在学,已经对竞赛失去信心了的样子,我还是回去跪跪文化课吧QAQ 第一道环套树DP...其实思想挺简单的,就把环拆开,分类处理.若拆成开的 ...
- 【BZOJ】1040: [ZJOI2008]骑士(环套树dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=1040 简直不能再神的题orz. 蒟蒻即使蒟蒻,完全不会. 一开始看到数据n<=1000000就 ...
- BZOJ 1040 骑士(环套树DP)
如果m=n-1,显然这就是一个经典的树形dp. 现在是m=n,这是一个环套树森林,破掉这个环后,就成了一个树,那么这条破开的边连接的两个顶点不能同时选择.我们可以对这两个点进行两次树形DP根不选的情况 ...
- 【CodeForces】835F Roads in the Kingdom
一.题目 题目描述 王国有\(n\)座城市与\(n\)条有长度的街道,保证所有城市直接或间接联通,我们定义王国的直径为所有点对最短距离中的最大值,现因财政危机需拆除一条道路并同时要求所有城市仍然联通, ...
- [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)
推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html 首先考虑树的情况,就是经典的树上概率DP.先DP出down表示从这个点向儿子走能走的期望长度,再DP ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- [BZOJ1040][ZJOI2008]骑士(环套树dp)
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5816 Solved: 2263[Submit][Status ...
随机推荐
- destoon 短信发送函数及短信接口修改
// $DT在common.inc.php中定义, $CACHE = cache_read('module.php'); $DT = $CACHE['dt']; 从缓存里读取网站配置信息. //$d ...
- 20181206(re,正则表达式,哈希)
1.re&正则表达式 2.hashlib 一:re模块&正则表达式 正则:正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描 ...
- BZOJ 5336: [TJOI2018]party
状压最长公共子序列的DP数组,一维最多K(15)个数,且相邻两个数的差不超过1,2^15种状态,预处理转移 #include<cstdio> #include<algorithm&g ...
- HDU 5614 Baby Ming and Matrix tree 树链剖分
题意: 给出一棵树,每个顶点上有个\(2 \times 2\)的矩阵,矩阵有两种操作: 顺时针旋转90°,花费是2 将一种矩阵替换为另一种矩阵,花费是10 树上有一种操作,将一条路经上的所有矩阵都变为 ...
- HDU 3376 费用流 Matrix Again
题意: 给出一个n × n的矩阵,每个格子中有一个数字代表权值,找出从左上角出发到右下角的两条不相交的路径(起点和终点除外),使得两条路径权值之和最大. 分析: 如果n比较小的话是可以DP的,但是现在 ...
- 基于EPOLL模型的局域网聊天室和Echo服务器
一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...
- python + selenium - selenium常用元素定位
1. Chrome定位工具 打开Chrome浏览器,按F12会弹出开发者工具选项,选择Elements: 1)鼠标点击最左边箭头 2)鼠标滑动到页面中你要操作的元素,单击一下 3)对应的html元素内 ...
- 03-python进阶-爬虫入门-正则
[urllib and urllib2] 这是两个python的网络模块 内置的 提供很好的网络访问的功能. #!coding:utf-8 import urllib2 res = urllib2.u ...
- 设计模式之单例模式 Singleton
核心作用 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. 常见应用场景 优点 由于单例模式只生成一个实例,减少了系统性开销,当一个对象的产生需要比较多的资源时,如读取配置,产生其他依赖对 ...
- javascript学习笔记 - 引用类型 Function
五 Function类型 每个函数都时Function类型的实例.函数也是对象. 声明函数: function func_name () {} //javascript解析器会在程序执行时率先读取函数 ...