最小生成树--Kruskal算法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
class UnionFind{ // 并查集模板
public:
vector<int> parent;
vector<int> rank;
UnionFind(int n){
parent.resize(n);
rank.resize(n);
for(int i = 0; i < n; ++i){
parent[i] = i;
rank[i] = 1;
}
}
int find(int x){ // 路径压缩查找
if(parent[x] == x) return x;
return parent[x] = find(parent[x]);
}
int find2(int x){
int ans = x;
while(ans != parent[ans]){
ans = parent[ans];
}
parent[x] = ans;
return ans;
}
void merge(int x, int y){ // 按秩合并
int xRoot = find(x);
int yRoot = find(y);
if(xRoot != yRoot){
if(rank[yRoot] <= rank[xRoot]) parent[yRoot] = xRoot;
else parent[xRoot] = yRoot; // xRoot挂到yRoot上
if(rank[xRoot] == rank[yRoot]) rank[xRoot]++;
}
}
};
void solve(int n, vector<vector<int>>& edges){ // 实现
ll ans = 0;
sort(edges.begin(), edges.end(), [&](const auto& x, const auto& y){ // 按边长对边进行排序
return x[2] < y[2];
});
UnionFind uf = UnionFind(n); // 并查集
int count = 0;
for(auto& ed : edges){ /
int x = ed[0], y = ed[1];
if(uf.find(x) != uf.find(y)){ // 合并
ans += ed[2];
uf.merge(x, y);
if(++count == n-1){ // 集合内边的个数为n-1时,结束
break;
}
}
}
cout<<ans<<endl;
return;
}
int main(){ // 数据初始化
int t,n,m;
cin>>t;
while(t--){
cin>>n>>m;
vector<vector<int>> edges(m+n,vector<int>(3));
int t;
for(int i = 1; i <= n; ++i){ // val[i] 边长
cin>>t;
edges[i-1] = {0,i,t};
}
int a,b;
for(int i = 0; i < m; ++i){ // 记录剩余m条边长
cin>>edges[n+i][0]>>edges[n+i][1]>>edges[n+i][2];
}
solve(n+1,edges);
}
return 0;
}