更新个板子。
https://www.cnblogs.com/orion7/p/7400556.html
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 105, INF = 0x3f3f3f3f;
int n, m;
int pre[maxn]; //点的前置点
int mincost[maxn]; //点到前置点的距离
bool vis[maxn]; //访问数组
bool used[maxn][maxn]; //最小生成树中使用的边
int cost[maxn][maxn]; //存图
int path[maxn][maxn]; //两点之间的最大边权值
void init() {
memset(pre, -1, sizeof(pre));
memset(path, 0, sizeof(path));
memset(vis, false, sizeof(vis));
memset(used, false, sizeof(used));
for (int i = 1; i <= n; i++)
mincost[i] = INF;
}
int prim() {
init();
int res = 0;
mincost[1] = 0;
while (true) {
//找到距离前置点最短的边的点
int v = -1;
for (int u = 1; u <= n; u++)
if (!vis[u] && (v == -1 || mincost[u] < mincost[v]))
v = u;
if (v == -1)
break;
if (pre[v] != -1) {
//标记使用
used[pre[v]][v] = used[v][pre[v]] = true;
//更新所有已经在生成树内的点与该点之间的最大权值
for (int u = 1; u <= n; u++) {
if (vis[u])
path[u][v] = path[v][u] = max(path[u][pre[v]], cost[v][pre[v]]);
}
}
vis[v] = true;
res += mincost[v];
//更新前置点
for (int u = 1; u <= n; u++) {
if (mincost[u] > cost[u][v]) {
mincost[u] = cost[u][v];
pre[u] = v;
}
}
}
return res;
}
int sec_mst(int res) {
int ans = INF;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (!used[i][j])
ans = min(ans, res - path[i][j] + cost[i][j]);
}
return ans;
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> n >> m;
init();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cost[i][j] = INF;
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
cost[a][b] = cost[b][a] = c;
}
int ans = prim();
printf("%d %d\n", ans, sec_mst(ans));
}
return 0;
}