题目传送门

  传送点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. 字符串ASCII码排序

    在对接第三方支付渠道的时候,第三方会要求参数按照ASCII码从小到大排序. 如下是渠道方有关生成签名规则的java代码示例: //初始化0010merkey.private文件: String mer ...

  2. H5进行录音,播放,上传

    废话不说,直接上代码吧 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type&q ...

  3. MFC CEdit控件 自动换行

    属性设置: Auto HScroll : False Auto VScroll : True Multiline        : Ture Want Return : Ture 亲自测试,值得信赖!

  4. mysql常用参数监控

      1.系统mysql的进程数 ps -ef | grep "mysql" | grep -v "grep" | wc –l 2.Slave_running m ...

  5. mysqldump导出数据

    如果导出的数据是乱码,需要制定--default-character-set= mysqldump -h wn-fala-v2-cluster.cluster-cczg3tb617nn.eu-cent ...

  6. callback源码分析——callbacks

    uvm的callback必须是提供者有预见性的留一些方法在function前后,这样在使用的时候,进行遍历调度即可 设计者,需要从uvm_callback定义一个基类,只定义function原型,定义 ...

  7. Lua用table模拟二维数组

    local array = {}; , , , , } , , , , } local row3 = {"I", "love", "lua" ...

  8. MapReduce的map个数调节 与 Hadoop的FileInputFormat的任务切分原理

    在对日志等大表数据进行处理的时候需要人为地设置任务的map数,防止因map数过小导致集群资源被耗光.可根据大表的数据量大小设置每个split的大小. 例如设置每个split为500M: set map ...

  9. window、linux安装jdk,excel 导入oracle,WebService,window 端口查看,svn服务安装,oracle用户解锁

    内存泄露分析插件http://download.eclipse.org/mat/1.3/update-site/birt插件http://download.eclipse.org//birt/upda ...

  10. 51nod 1057 N的阶乘 (大数运算)

    输入N求N的阶乘的准确值.   Input 输入N(1 <= N <= 10000) Output 输出N的阶乘 Input示例 5 Output示例 120 压位: 每个数组元素存多位数 ...