题目传送门

  传送点I

  传送点II

  传送点III

题目大意

  给定一颗基环树,要求删去其中一条边,使得剩下的图形是一棵树,并且最长路的长度最短,求最长路的最短长度。

  路径可以分为两部分:跨过环 和 在树内部。

  要删除一条边,使图形变为一棵树,那么只能删去环上的一条边,因此,我们无法改变第二部分的路径,但是可以改变第一部分。

  对于第二部分可以通过两次搜索或者树形动态规划解决。

  对于第一部分,考虑枚举删去环上的一条边。但是发现仍然不太方便处理,因为不好维护环上的信息。仍然考虑剖环成链。

  假设环的大小为$k$,从剖点开始依次将所有点标号1到$k$。

  当一条边被删除后,第二部分可能成为答案的情况有两种:

  1. 不跨过剖点和被删边的路径
  2. 跨过剖点但不经过被删边的路径

  因此考虑维护一些数组。

  1. 在$1, 2, \cdots, i$及其所在的树中的最长路。
  2. 从$1$开始,到$1, 2, \cdots, i$及其所在的树中的最长路。
  3. 在$k, k - 1, \cdots, i$及其所在的树中的最长路。
  4. 从$k$开始,到$k, k - 1, \cdots, i$及其所在的树中的最长路。

  这四个部分都可以线性预处理出来。然后枚举删掉的环边就能统计第一部分的答案。

Code

 /**
* Codeforces
* Problem#835F
* Accepted
* Time: 155ms
* Memory: 27100k
*/
#include <bits/stdc++.h>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean; typedef class Edge {
public:
int ed, nx, w; Edge(int ed = , int nx = , int w = ):ed(ed), nx(nx), w(w) { }
}Edge; typedef class MapManager {
public:
int ce;
int* h;
Edge* es; MapManager() { }
MapManager(int n, int m):ce(-) {
h = new int[(n + )];
es = new Edge[(m + )];
memset(h, -, sizeof(int) * (n + ));
} void addEdge(int u, int v, int w) {
es[++ce] = Edge(v, h[u], w);
h[u] = ce;
} Edge& operator [] (int pos) {
return es[pos];
}
}MapManager; #define ll long long const signed ll llf = (signed ll) ((~0ull) >> ); int n;
int ccir, cc;
MapManager g;
stack<int> s;
boolean *vis, *icir;
int *cir, *nw;
ll *ap[], *cp[], *dep, *dis; inline void init() {
scanf("%d", &n);
vis = new boolean[(n + )];
icir = new boolean[(n + )];
cir = new int[(n + )];
nw = new int[(n + )];
dep = new ll[(n + )];
dis = new ll[(n + )];
for (int i = ; i < ; i++) {
ap[i] = new ll[(n + )];
cp[i] = new ll[(n + )];
}
g = MapManager(n, n << );
memset(vis, false, sizeof(boolean) * (n + ));
memset(icir, false, sizeof(boolean) * (n + ));
for (int i = , u, v, w; i <= n; i++) {
scanf("%d%d%d", &u, &v, &w);
g.addEdge(u, v, w);
g.addEdge(v, u, w);
}
} boolean getLoop(int p, int fa) {
if (vis[p]) {
ccir = ;
int cur = ;
do {
cur = s.top();
s.pop();
icir[cur] = true;
cir[ccir++] = cur;
cc = ccir - ;
} while (cur != p);
return true;
}
vis[p] = true;
s.push(p);
for (int i = g.h[p]; ~i; i = g[i].nx) {
int e = g[i].ed;
if (e == fa) continue;
if (getLoop(e, p)) {
if (icir[p]) {
nw[cc] = g[i].w;
cc = (cc + ) % ccir;
}
return true;
}
}
s.pop();
return false;
} void dfs(int p, int fa, ll dep, int& fn, ll& fd) {
if (dep > fd)
fd = dep, fn = p;
for (int i = g.h[p]; ~i; i = g[i].nx) {
int e = g[i].ed;
if (e == fa || icir[e]) continue;
dfs(e, p, dep + g[i].w, fn, fd);
}
} inline void solve() {
getLoop(, );
ll fixedd = ;
// for (int i = 0; i < ccir; i++)
// cerr << cir[i] << " ";
// cerr << endl;
// for (int i = 0; i < ccir; i++)
// cerr << nw[i] << " ";
// cerr << endl;
for (int i = , fn, fbn; i < ccir; i++) {
fn = -, dep[i] = ;
dep[i] = , dfs(cir[i], , , fn, dep[i]);
if (~fn)
icir[cir[i]] = false, dfs(fn, , , fbn, fixedd), icir[cir[i]] = true;
}
dis[] = ;
for (int i = ; i < ccir; i++)
dis[i] = nw[i - ];
for (int i = ; i < ccir; i++)
dis[i] += dis[i - ];
ll mi = dep[];
ap[][] = -llf, cp[][] = dep[];
for (int i = ; i < ccir; i++) {
ap[][i] = max(ap[][i - ], dep[i] + dis[i] + mi);
mi = max(mi, dep[i] - dis[i]);
cp[][i] = max(cp[][i - ], dep[i] + dis[i]);
}
mi = dep[ccir - ] + dis[ccir - ];
ap[][ccir - ] = -llf, cp[][ccir - ] = dep[ccir - ];
for (int i = ccir - ; ~i; i--) {
ap[][i] = max(ap[][i + ], dep[i] - dis[i] + mi);
mi = max(mi, dep[i] + dis[i]);
cp[][i] = max(cp[][i + ], dep[i] + dis[ccir - ] - dis[i]);
}
ll ans = ap[][ccir - ];
for (int i = ; i < ccir - ; i++)
ans = min(max(max(ap[][i], ap[][i + ]), cp[][i] + cp[][i + ] + nw[ccir - ]), ans);
printf(Auto, max(ans, fixedd));
} int main() {
init();
solve();
return ;
}

Codeforces 835F Roads in the Kingdom - 动态规划的更多相关文章

  1. Codeforces 835F Roads in the Kingdom (环套树 + DP)

    题目链接 Roads in the Kingdom 题意  给出一个环套树的结构,现在要删去这个结构中的一条边,满足所有点依然连通. 删边之后的这个结构是一棵树,求所有删边情况中树的直径的最小值. 显 ...

  2. 【CodeForces】835F Roads in the Kingdom

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

  3. Codeforces 835 F. Roads in the Kingdom

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

  4. Codeforces 835 F Roads in the Kingdom(树形dp)

    F. Roads in the Kingdom(树形dp) 题意: 给一张n个点n条边的无向带权图 定义不便利度为所有点对最短距离中的最大值 求出删一条边之后,保证图还连通时不便利度的最小值 $n & ...

  5. 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 ...

  6. Roads in the Kingdom CodeForces - 835F (直径)

    大意: 给定一个基环树, 求删除一条环上的边使得直径最小. 直径分两种情况 环上点延伸的树内的直径 两个环上点的树内深度最大的点匹配 第一种情况直接树形dp求一下, 第二种情况枚举删除的环边, 线段树 ...

  7. codeforces:Roads in the Kingdom分析和实现

    题目大意:国家有n个城市,还有n条道路,每条道路连通两个不同的城市,n条道路使得所有n个城市相互连通.现在国家经费不足,要关闭一条道路.国家的不便度定义为国家中任意两个不同的城市之间的距离的最大值,那 ...

  8. HDU 1025 Constructing Roads In JGShining's Kingdom[动态规划/nlogn求最长非递减子序列]

    Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65 ...

  9. Codeforces 581F Zublicanes and Mumocrates - 树形动态规划

    It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The ...

随机推荐

  1. cocos2dx - JS - 碰撞检测

    碰撞检测是游戏的一个重要组成部分,我们这里使用一种最简单的方法,就是获取精灵的矩形碰撞框.当然圆形的碰撞检测也比较简单,其他形状就复杂多了.首先是如何获取矩形碰撞框:var hBox=this.her ...

  2. 21.JQ的监听事件(点击div外面可以让它消失)

    JQ的监听事件(点击div外面可以让它消失) //监听整个页面 $(document).bind("click", function() { //给需要的对象赋予事件 $(&quo ...

  3. 3.十分钟搞定Vue搭建

    Vue推荐开发环境 Node.js 6.2.0.npm 3.8.9.webpack 1.13.vue-cli 2.5.1.webstrom2016 现在开始安装环境 安装nodejs 可以在终端里下载 ...

  4. is_readable() 函数检查指定的文件是否可读。

    定义和用法 is_readable() 函数判断指定文件名是否可读. 语法 is_readable(file) 参数 描述 file 必需.规定要检查的文件. 说明 如果由 file 指定的文件或目录 ...

  5. linux telnet命令

    telnet命令通常用来远程登录.telnet程序是基于TELNET协议的远程登录客户端程序.Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户 ...

  6. Vue+webpack项目中实现跨域的http请求

    目前Vue项目中对json数据的请求一般使用两个插件vue-resource和axios, 但vue-resource已经不再维护, 而axios是官方推荐的且npm下载量已经170多万,github ...

  7. 21Oracle数据库和实例

    Oracle数据库:相关的操作系统文件(即储存在计算机硬盘上的文件)的集合,这些文件组织在一起,成为一个逻辑整体,即为Oracle数据库.物理存在 Oracle实例:位于物理内存里的数据结构,它由操作 ...

  8. case when 遇到varchar转为int类型值失败的错误

    问题描述: 在Sql Server 2005下, 使用如下语句报错:在将 varchar 值 '大' 转换成数据类型 int 时失败. 注:status 是整型字段 select ff=  case ...

  9. XML小结

    一.因为某些字符在xml格式中,具有特殊意义,所以当我们需要使用它本身的意思的时候,就要用其他东西来代替它,否则会产生错误 < < less than > > greater ...

  10. html5-微格式-时间的格式

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...