题目链接 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)的更多相关文章

  1. Codeforces 835F Roads in the Kingdom - 动态规划

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗基环树,要求删去其中一条边,使得剩下的图形是一棵树,并且最长路的长度最短,求最长路的最短长度. 路径可以分为两部分:跨过环 和 在树内 ...

  2. 【BZOJ】1040: [ZJOI2008]骑士 环套树DP

    [题意]给定n个人的ai和bi,表示第i个人能力值为ai且不能和bi同时选择,求能力值和最大的选择方案.n<=10^6. [算法]环套树DP(基环树) [题解]n个点n条边——基环森林(若干环套 ...

  3. 【距离GDKOI:44天&GDOI:107天】【BZOJ1040】[ZJOI2008] 骑士 (环套树DP)

    其实已经准备退役了,但GDOI之前还是会继续学下去的!!当成兴趣在学,已经对竞赛失去信心了的样子,我还是回去跪跪文化课吧QAQ 第一道环套树DP...其实思想挺简单的,就把环拆开,分类处理.若拆成开的 ...

  4. 【BZOJ】1040: [ZJOI2008]骑士(环套树dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1040 简直不能再神的题orz. 蒟蒻即使蒟蒻,完全不会. 一开始看到数据n<=1000000就 ...

  5. BZOJ 1040 骑士(环套树DP)

    如果m=n-1,显然这就是一个经典的树形dp. 现在是m=n,这是一个环套树森林,破掉这个环后,就成了一个树,那么这条破开的边连接的两个顶点不能同时选择.我们可以对这两个点进行两次树形DP根不选的情况 ...

  6. 【CodeForces】835F Roads in the Kingdom

    一.题目 题目描述 王国有\(n\)座城市与\(n\)条有长度的街道,保证所有城市直接或间接联通,我们定义王国的直径为所有点对最短距离中的最大值,现因财政危机需拆除一条道路并同时要求所有城市仍然联通, ...

  7. [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)

    推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html 首先考虑树的情况,就是经典的树上概率DP.先DP出down表示从这个点向儿子走能走的期望长度,再DP ...

  8. [BZOJ1791][IOI2008]Island岛屿(环套树DP)

    同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...

  9. [BZOJ1040][ZJOI2008]骑士(环套树dp)

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5816  Solved: 2263[Submit][Status ...

随机推荐

  1. GoF23种设计模式之行为型模式之备忘录模式

    一.概述         在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象的外部保存这个状态.以便以后可以将该对象恢复到原先保存的状态. 二.适用性 1.当需要保存一个对象在某个时刻的状态( ...

  2. python 中 * 与**的使用

    1.参数中使用如果是函数定义中参数前的*表示的是将调用时的多个参数放入元组中,**则表示将调用函数时的关键字参数放入一个字典中 如定义以下函数 def func(*args): print(args) ...

  3. Java-basic-2-

    接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类. 如果一个类定义在某个包中,那么package语句应该在源文件的首行. 如果源文件包含import语句,那么应该放在package语句和 ...

  4. 做ios工程时,把UI从xib移动到代码中遇到的问题

    由于四期要做多语言版本,带xib页面的工程做多语言版本比较麻烦,再加上现在已经习惯了代码中的viewdidload函数中初始化控件,所以就把两个页面从xib移到代码中去了. 在修改后加载页面会遇到ba ...

  5. JVM执行子系统探究——类文件结构初窥

    类文件(.class)是搞java的都非常熟悉的文件,一般我们在编写java之后文件之后,首先通过javac工具生成.class类字节码文件,而后在执行程序的时候由虚拟机加载执行.那么为什么要生成.c ...

  6. Android工具 Hierarchy Viewer 分析

    Hierarchy Viewer是随AndroidSDK发布的工具,位置在tools文件夹下,名为hierarchyviewer.bat.它是Android自带的非常有用而且使用简单的工具,可以帮助我 ...

  7. git 强制回到以前版本

    git reset dfd3e36a641340a0b86f811df869c4375fabeff2 --hard

  8. MFC自绘按钮的实现,按钮动态效果

    最近项目需要实现按钮的动态效果,多方学习,现在终于能实现一些功能了. 过程如下: 第一,新建一MFC对话框应用程序. 第二,删除自带按钮,并添加两个按钮,button1,button2,ID为IDB_ ...

  9. MyBatis配置文件中报错:URI is not registered(Settings | Languages & Frameworks | Schemas and DTDs)

    如下错误: 解决办法: 在file->Settings中添加如下图所示: URI为出现红色部分的地址 点击OK后会发现: 这样就解决了!

  10. 大数据学习——spark-steaming学习

    官网http://spark.apache.org/docs/latest/streaming-programming-guide.html 1.1.  用Spark Streaming实现实时Wor ...