UvaLive 5026 Building Roads

时间:2024-01-03 19:09:38

传送门

Time Limit: 3000MS

Description

There is a magic planet in the space. There is a magical country on the planet. There are N cities in the country. The country is magical because there are exactly N −1 magic roads between the N cities, and from each city, it is possible to visit any other city. But after the huge expansion of the country, the road system seems to be messy. The moderator decided to rebuild the road system. As a worker, I cannot do too much things. I could just move one road to another position connecting arbitrary 2 cities using my magic, keeping its length unchanged. Of course, afterwards all the N cities have to be still connected. I wonder how to move in order to make the farthest distance between any two cities minimum. Could you solve it for me?

Input

The first line of the input is one integer T (T ≤ 10), and then T test cases follow. Each test case begins with a line contains only one integer N (N ≤ 2500), means there are N magic cities. The cities are numbered from 0 to N − 1. Following N − 1 lines, each line has 3 integers a, b and c, means there is a magic road between a and b with distance c. (0 ≤ a, b < N, 0 < c ≤ 1000)

Output

For each test case, output the case number and the corresponding minimum farthest distance. See sample for detailed format.

Sample Input

2

4

0 1 2

1 2 2

2 3 2

5

0 1 1

1 2 2

2 3 3

3 4 4

Sample Output

Case 1: 4

Case 2: 7

-----------------------------------------------------------

这是2010年天津站的B题

题意:给定一棵带边权的树,可将其中的一条边重连,形成一棵新树,求新树中最长路的最小值。

Solution:

枚举边,求重连该边后新树中最长路径的最小值。

求法:

设删去长为c的边(u,v)后形成的两子树的点集分别是 L, R

分别求两子树中从每个节点u出发的最长距离d[u](复杂度O(n), 参考这篇博客), 显然新边应连在两子树中d最小的两节点之间。

这样得到的新树中的最长路径就是max(max{d[u], U}, min{d[u] : ∈ L, d[v] : ∈ R} + c)

总复杂度O(n^2)。

 Implementation:

#include <bits/stdc++.h>
using namespace std;
const int N(+);
typedef pair<int,int> P;
struct edge{
int u, v, c, flag, nt;
}E[N<<];
int head[N], dp[][N];
void dfs1(int u, int f){
dp[][u]=dp[][u]=;
for(int i=head[u]; ~i; i=E[i].nt){
int &v=E[i].v, &c=E[i].c;
if(v==f||E[i].flag) continue;
dfs1(v, u);
if(dp[][v]+c > dp[][u])
dp[][u]=dp[][u], dp[][u]=dp[][v]+c;
else dp[][u]=max(dp[][u], dp[][v]+c);
}
}
P dfs2(int u, int f){
int mi, ma=mi=max(dp[][u], dp[][u]);
for(int i=head[u]; ~i; i=E[i].nt){
int &v=E[i].v, &c=E[i].c;
if(v==f||E[i].flag) continue;
dp[][v]=c+max(dp[][u], dp[][u]==dp[][v]+c?dp[][u]:dp[][u]);
P res=dfs2(v, u);
mi=min(mi, res.first), ma=max(ma, res.second);
}
return {mi, ma};
}
int main(){
int T; scanf("%d", &T);
for(int n, cs=, ans; T--;){
scanf("%d", &n);
memset(head, -, sizeof(head));
for(int i=, u, v, c, id=; i<n; ++i){
scanf("%d%d%d", &u, &v, &c);
E[id]={u, v, c, , head[u]}, head[u]=id++;
E[id]={v, u, c, , head[v]}, head[v]=id++;
}
P p1, p2;
ans=INT_MAX;
for(int i=; i<(n-)<<; i+=){
E[i].flag=E[i^].flag=;
int &u=E[i].u, &v=E[i].v, &c=E[i].c;
dfs1(u, u), dp[][u]=, p1=dfs2(u, u);
dfs1(v, v), dp[][v]=; p2=dfs2(v, v);
ans=min(ans, max(max(p1.second, p2.second), p1.first+p2.first+c));
E[i].flag=E[i^].flag=;
}
printf("Case %d: %d\n", ++cs, ans);
}
}