每次选权值最小的边,如果构成环,则舍弃,选择次小的,直到所有的点都包含在生成树中。
图解:https://blog.csdn.net/qq_41754350/article/details/81460643
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 505;
const int MAXM = 25005;
int F[MAXN]; //并查集
struct Edge {
int u, v, w;
}edge[MAXM];
int tol;//边数
void addedge(int u, int v, int w) {
edge[tol].u = u;
edge[tol].v = v;
edge[tol++].w = w;
}
bool cmp(Edge a, Edge b) {
return a.w < b.w;
}
int Find(int x) {
while (F[x] != -1) {
x = F[x];
}
return x;
}
int Kruskal(int n) {
memset(F, -1, sizeof(F));
//对边从小到大排序
sort(edge, edge + tol, cmp);
int cnt = 0;
int ans = 0;
for (int i = 0; i < tol; ++i) {
int u = edge[i].u;
int v = edge[i].v;
int w = edge[i].w;
//查看所选边的两个点是否在同一个集合中(在的话则构成环,不可)
int t1 = Find(u);
int t2 = Find(v);
if (t1 != t2) {
ans += w;
F[t1] = t2;
cnt++;
}
if (cnt == n - 1)
break;
}
if (cnt < n - 1)
return -1;
else
return ans;
}
int main() {
//freopen("in.txt","r",stdin);
int T;
cin >> T;
int n;
int c;
while (T--)
{
cin >> n;
tol = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cin >> c;
addedge(i, j, c);
}
}
cout << Kruskal(n) << endl;
}
return 0;
}