Codeforces 835 F. Roads in the Kingdom
Posted mangoyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 835 F. Roads in the Kingdom相关的知识,希望对你有一定的参考价值。
In the Kingdom K., there are n towns numbered with integers from 1 to n. The towns are connected by n bi-directional roads numbered with integers from 1 to n. The i-th road connects the towns ui and vi and its length is li. There is no more than one road between two towns. Also, there are no roads that connect the towns with itself.
Let‘s call the inconvenience of the roads the maximum of the shortest distances between all pairs of towns.
Because of lack of money, it was decided to close down one of the roads so that after its removal it is still possible to reach any town from any other. You have to find the minimum possible inconvenience of the roads after closing down one of the roads.
The first line contains the integer n (3?≤?n?≤?2·105) — the number of towns and roads.
The next n lines contain the roads description. The i-th from these lines contains three integers ui, vi, li (1?≤?ui,?vi?≤?n, 1?≤?li?≤?109) — the numbers of towns connected by the i-th road and the length of the i-th road. No road connects a town to itself, no two roads connect the same towns.
It‘s guaranteed that it‘s always possible to close down one of the roads so that all the towns are still reachable from each other.
Print a single integer — the minimum possible inconvenience of the roads after the refusal from one of the roads.
题目大意,给你一个基环树,可以日掉任意一条环边,变成一颗树,问日掉之后的树的直径最小是多少
考虑直径可能由两部分组成,答案是两种之间的最大值
第一种就是外向树内的直径的最大值,这个只需要随便dp一下即可,不需要过多讨论
考虑最终的直径若经过原来的环,那么直径必然是环上的一段距离加上两个端点的外向树的最大深度
将环求出来破环成链之后,对于任意长度为len的一段,答案就是dist(x, y) + dep[y] + dep[y],其中x, y是这一段中的元素
考虑对破出来的链做前缀和,记为s,那么答案就是s[x] - s[y] + dep[x] + dep[y],把与x有关的放在一边,即最大化(s[x] + dep[x]) - (s[x] - dep[y])
那么就变成最大化前一项,最小化后一项,且不能选到相同的点,用两个set维护并且判掉端点重叠的情况即可
/*program by mangoyang*/ #include<bits/stdc++.h> #define inf (0x7f7f7f7f) #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) typedef long long ll; using namespace std; template <class T> inline void read(T &x){ int f = 0, ch = 0; x = 0; for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = 1; for(; isdigit(ch); ch = getchar()) x = x * 10 + Qch - 48; if(f) x = -x; } #define int ll #define N (600005) int a[N], b[N], head[N], nxt[N], cnt; int st[N], ct[N], vis[N], success; int g[N], dep[N], c[N], s[N], tot, top, n; struct Node{ int val, id; bool operator < (const Node &A) const{ return val < A.val; } }; multiset<Node> s1, s2; inline void add(int x, int y, int z){ a[++cnt] = y, b[cnt] = z; nxt[cnt] = head[x], head[x] = cnt; } inline void Getcircle(int u, int fa){ vis[u] = 1; for(int p = head[u]; p; p = nxt[p]){ int v = a[p]; if(v == fa) continue; if(!vis[v]){ st[++top] = v, ct[top] = b[p]; Getcircle(v, u); } else{ int pos = 1; for(int i = 1; i <= top; i++) if(st[i] == v){ pos = i; break; } for(int i = pos; i <= top; i++) c[++tot] = st[i], s[tot] = ct[i]; s[1] = b[p]; return (void) (success = 1); } if(success) return; } if(success) return; vis[u] = 0, top--; } inline int dfs(int u, int fa){ int mx = u; for(int p = head[u]; p; p = nxt[p]){ int v = a[p]; if(v != fa && !vis[v]){ dep[v] = dep[u] + b[p]; int now = dfs(v, u); if(dep[now] > dep[mx]) mx = now; } } return mx; } inline int dfs2(int u, int fa, int dis, int t){ int res = dis; for(int p = head[u]; p; p = nxt[p]){ int v = a[p]; if(v != fa){ if(vis[v] && t) continue; if(!vis[v]){ int now = dfs2(v, u, dis + b[p], t); if(now > res) res = now; } else{ int now = dfs2(v, u, dis + b[p], 1); if(now > res) res = now; } } } return res; } inline ll calc1(){ multiset<Node>::iterator it2 = s2.begin(); int id = it2 -> id; s1.erase(s1.find((Node){s[id] + g[id], id})); multiset<Node>::iterator it1 = s1.end(); it1--; int ans = it1 -> val - it2 -> val; s1.insert((Node){s[id] + g[id], id}); return ans; } inline ll calc2(){ multiset<Node>::iterator it1 = s1.end(); it1--; int id = it1 -> id; s2.erase(s2.find((Node){s[id] - g[id], id})); multiset<Node>::iterator it2 = s2.begin(); int ans = it1 -> val - it2 -> val; s2.insert((Node){s[id] - g[id], id}); return ans; } inline ll calc(){ return max(calc1(), calc2()); } main(){ read(n); if(n <= 2) return puts("0"), 0; for(int i = 1, x, y, z; i <= n; i++){ read(x), read(y), read(z); add(x, y, z), add(y, x, z); } ll ans = 0; st[++top] = 1, Getcircle(1, 0); for(int i = 1; i <= n; i++) vis[i] = 0; for(int i = 1; i <= tot; i++) vis[c[i]] = 1; for(int i = 1; i <= tot; i++) cout << c[i] << " "; cout << endl; for(int i = 1; i <= tot; i++) cout << s[i] << " "; cout << endl; for(int i = 1; i <= tot; i++){ int mx = dfs(c[i], 0); g[i] = dep[mx], ans = max(ans, g[i]); ans = max(ans, dfs2(mx, 0, 0, mx == c[i] ? 1 : 0)); } for(int i = 1; i <= tot; i++) g[i+tot] = g[i]; for(int i = 1; i <= tot; i++) s[i+tot] = s[i]; tot *= 2; for(int i = 1; i <= tot; i++) cout << g[i] << " "; cout << endl; for(int i = 1; i <= tot; i++) s[i] += s[i-1]; for(int i = 1; i <= tot; i++) cout << s[i] << " "; cout << endl; for(int i = 1; i <= tot / 2; i++){ s1.insert((Node){s[i] + g[i], i}); s2.insert((Node){s[i] - g[i], i}); } ll tmp = calc(); for(int i = 2; i <= tot / 2; i++){ int l = i, r = i + tot / 2 - 1; s1.insert((Node){s[r] + g[r], r}); s2.insert((Node){s[r] - g[r], r}); s1.erase(s1.find((Node){s[l-1] + g[l-1], l - 1})); s2.erase(s2.find((Node){s[l-1] - g[l-1], l - 1})); tmp = min(tmp, calc()); } cout << Max(ans, tmp); return 0; }
以上是关于Codeforces 835 F. Roads in the Kingdom的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 835F Roads in the Kingdom - 动态规划
题解-CodeForces835F Roads in the Kingdom
Roads in the Kingdom CodeForces - 835F (直径)
Codeforces 908 F. New Year and Rainbow Roads(思维)