[TJOI2017]城市
## 题目大意: 去掉这个图中的一条边,再把这条边加到其他两个节点上,这条边的权值不变,使得树的直径最短。
## 思路: 枚举每一条边,使它成为那条被删除的边,然后计算出被分割成的两部分的中心点(到该部分中最远的点的距离最小的点)。然后每次取min就行。时间复杂度n2.
#include <iostream>
#include <cstring>
using namespace std;
#define ll long long
const int maxn = 1e3 + 5 ;
const int inf = 0x3f3f3f3f ;
struct node{
int nxt, to, valu;
} s[ maxn] ;
int mx[ maxn] ;
ll ans = 0 ;
int tot = 0 , f[ maxn] , t[ maxn] , head[ maxn] , path[ maxn] , d1[ maxn] , d2[ maxn] , up[ maxn] , w[ maxn] ;
int mx1[ maxn] , mx2[ maxn] ;
int res, mxlong = 0 ; ;
void add ( int u, int v, int valu) {
s[ tot] . nxt = head[ u] ;
s[ tot] . to = v;
s[ tot] . valu = valu;
head[ u] = tot ++ ;
}
void dfs1 ( int u, int fa) {
d1[ u] = 0 ; d2[ u] = 0 ;
for ( int i = head[ u] ; ~ i; i = s[ i] . nxt) {
int to = s[ i] . to;
if ( to == fa) continue ;
dfs1 ( to, u) ;
int dep = s[ i] . valu + d1[ to] ;
if ( dep > d1[ u] ) {
path[ u] = to;
d2[ u] = d1[ u] ;
d1[ u] = dep;
}
else
d2[ u] = max ( d2[ u] , dep) ;
}
mxlong = max ( mxlong, d1[ u] + d2[ u] ) ;
}
void dfs2 ( int u, int fa) {
res = min ( res, max ( up[ u] , d1[ u] ) ) ;
for ( int i = head[ u] ; ~ i; i = s[ i] . nxt) {
int to = s[ i] . to;
if ( to == fa) continue ;
if ( path[ u] == to) {
up[ to] = max ( up[ u] , d2[ u] ) + s[ i] . valu;
}
else up[ to] = max ( up[ u] , d1[ u] ) + s[ i] . valu;
dfs2 ( to, u) ;
}
}
int main ( ) {
int n;
cin >> n;
memset ( head, - 1 , sizeof head) ;
for ( int i = 1 ; i < n; i ++ ) {
int u, v, ww;
cin >> u >> v >> ww;
f[ i] = u;
t[ i] = v;
w[ i] = ww;
add ( u, v, ww) ;
add ( v, u, ww) ;
}
int ans = 1000000000 ;
for ( int i = 1 ; i < n; i ++ ) {
mxlong = 0 ;
dfs1 ( f[ i] , t[ i] ) ;
dfs1 ( t[ i] , f[ i] ) ;
res = inf;
up[ f[ i] ] = 0 ;
up[ t[ i] ] = 0 ;
dfs2 ( f[ i] , t[ i] ) ;
int t1 = res;
res = inf;
dfs2 ( t[ i] , f[ i] ) ;
int t2 = res;
ans = min ( max ( t1 + t2 + w[ i] , mxlong) , ans) ;
}
cout << ans ;
}