use标记当前边是否属于最小生成树。
d[i][j]代表从i->j的瓶颈路。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int n , m , a , b , c;
int map[105][105];
int dist[105] , vis[105] , ans1 , ans2 , use[105][105] , p[205];
int d[105][105];
void prim(){
int tid , tmin;
ans1 = 0;
memset(vis , 0 , sizeof(vis));
memset(dist , 0 , sizeof(dist));
memset(p , -1 , sizeof(p));
for(int i = 1 ; i <= n ; i ++){
dist[i] = inf;
}
dist[1] = 0;
p[1] = -1;
for(int i = 0 ; i < n; i ++){
//printf("i = %d\n" , i);
tid = -1;
tmin = inf;
for(int j = 1 ; j <= n ; j ++){
if(vis[j] == 0 && tmin > dist[j]){
tmin = dist[j];
tid = j;
}
}
ans1 += tmin;
//printf("tmin = %d\n" , tmin);
vis[tid] = 1;
for(int j = 1 ; j <= n ; j ++){
if(vis[j] == 0 && dist[j] > map[tid][j]){
dist[j] = map[tid][j];
p[j] = tid;
//printf("j = %d pos = %d\n" , j , tid);
}
}
}
return ;
}
void dfs(int v){
for(int u = 1 ; u <= n ; u ++){
if(vis[u] == 0 && p[u] == v){
vis[u] = 1;
for(int x = 1 ; x <= n ; x ++){
if(vis[x] == 1 && x != u){
d[x][u] = d[u][x] = max(d[x][v] , map[u][v]);
}
}
dfs(u);
}
}
return ;
}
void Second_MST(){
ans2 = inf;
for(int i = 1;i <= n; ++i){
for(int j = 1;j <= n; ++j){
if(use[i][j] == 1){
if(ans1 + map[i][j] - d[i][j] < ans2)
ans2 = ans1 + map[i][j] - d[i][j];
}
}
}
}
int main(){
int t;
scanf("%d" , &t);
while(t --){
memset(map , inf , sizeof(map));
memset(use , 0 , sizeof(use));
scanf("%d%d" , &n , &m);
for(int i = 0 ; i < m ; i ++){
scanf("%d%d%d" , &a , &b , &c);
map[a][b] = c;
map[b][a] = c;
use[a][b] = use[b][a] = 1;
}
prim();
printf("%d " , ans1);
memset(vis , 0 , sizeof(vis));
memset(d , 0 , sizeof(d));
vis[1] = true;
dfs(1);
for(int i = 1 ; i <= n ; i ++){
if(p[i] != -1){
use[p[i]][i] = use[i][p[i]] = 0;
}
}
Second_MST();
printf("%d\n" , ans2);
}
}