借鉴了网上一个大牛的代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 2500 + 123;
struct EDGE
{
int v, val, next;
bool flag;
}edge[MAXN * 2];
int cnt = 0;
int head[MAXN];
int dis[MAXN];
int pre[MAXN];
bool vis[MAXN];
int q[MAXN];
void addedge(int x, int y, int z)
{
edge[cnt].v = y;
edge[cnt].val = z;
edge[cnt].flag = true;
edge[cnt].next = head[x];
head[x] = cnt++;
}
int dfs(int src, int& rmin)
{
memset(dis, -1, sizeof(dis));
int front = 0;
int rear = 0;
q[rear++] = src;
dis[src] = 0;
int id = src;
while(front < rear)//找出直径的一端
{
int now = q[front++];
for(int p = head[now]; p != -1; p = edge[p].next)
{
if(!edge[p].flag) continue;//删除的边
int v = edge[p].v;
if(dis[v] != -1) continue;
dis[v] = dis[now] + edge[p].val;
q[rear++] = v;
if(dis[v] > dis[id])
{
id = v;
}
}
}
front = rear = 0;
src = id;
q[rear++] = src;
dis[src] = 0;
id = src;
vis[src] = true;
while(front < rear)
{
int now = q[front++];
for(int p = head[now]; p != -1; p = edge[p].next)
{
if(!edge[p].flag) continue;//删除的边
int v = edge[p].v;
if(vis[v]) continue;
dis[v] = dis[now] + edge[p].val;
pre[v] = now;
q[rear++] = v;
vis[v] = true;
if(dis[v] > dis[id])
{
id = v;
}
}
}
int half = dis[id] / 2;
int small = dis[id];
rmin = 0;
for(int i = id; i != src; i = pre[i])//找到那个根节点
{
if(dis[i] >= half && dis[pre[i]] <= half)
{
rmin=min(dis[i],small-dis[pre[i]]);
break;
}
}
return small;
}
int main()
{
int T;
int n;
int x, y, z;
scanf("%d", &T);
for(int cas = 1; cas <= T; cas++)
{
scanf("%d", &n);
if(n == 1)
{
printf("Case %d: 0\n",cas);
continue;
}
cnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1; i < n; i++)
{
scanf("%d%d%d", &x, &y, &z);
addedge(x, y, z);
addedge(y, x, z);
}
//开始枚举删边
int a, b, c, d;
int ans = 1 << 30;
for(int i = 0; i < cnt; i+=2) //注意加2不是加1
{
edge[i].flag = false;
edge[i ^ 1].flag = false;
memset(vis, 0, sizeof(vis));
for(int j = 0; j < n; j++)
if(!vis[j])
{
a = dfs(j, c);//a是这个部分的直径,c是这个部分选定的使最长路最短的根节点发出的最长路
break;
}
for(int j = 0; j < n; j++)
if(!vis[j])
{
b = dfs(j, d);
break;
}
int rmax = max(a, b);
rmax = max(rmax, c + d + edge[i].val);
if(rmax < ans) ans = rmax;
edge[i].flag = true;
edge[i ^ 1].flag = true;
}
printf("Case %d: %d\n", cas, ans);
}
return 0;
}