最小直径生成树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 210
using namespace std;
const int inf = 0x7fffffff / 2;
int n, m;
int f[maxn][maxn], d[maxn][maxn], p[maxn][maxn];
void MST(){
//Floyd
for(int k = 1; k <= n; k ++)
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
if(i != j && j != k && k != i)
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
//getrank
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++)
p[i][j] = j;
for(int j = 1; j <= n; j ++)
for(int k = j + 1; k <= n; k ++)
if(f[i][p[i][j]] > f[i][p[i][k]])
swap(p[i][j], p[i][k]);
}
//main
int ans = inf;
for(int u = 1; u <= n; u ++){
for(int v = 1; v <= n; v ++){
if(d[u][v] != inf){
ans = min(ans, min(f[u][p[u][n]] << 1, f[v][p[v][n]] << 1));
int t = n;
for(int k = n - 1; k >= 1; k --){
if(f[v][p[u][t]] < f[v][p[u][k]]){
ans = min(ans, f[u][p[u][k]] + f[v][p[u][t]] + d[u][v]);
t = k;
}
}
}
}
}
printf("%d\n", ans);
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
f[i][j] = d[i][j] = inf;
for(int i = 1; i <= n; i ++)
f[i][i] = d[i][i] = 0;
int u, v, dis;
for(int i = 1; i <= m; i ++){
scanf("%d%d%d", &u, &v, &dis);
f[u][v] = f[v][u] = d[u][v] = d[v][u] = dis;
}
MST();
return 0;
}