并查集通俗讲解见此:
https://www.cnblogs.com/-new/p/6662301.html
最小生成树(并查集实现)讲解见此:
https://www.cnblogs.com/nbalive2001/p/4979667.html
代码实现:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
struct edge{ //边的结构体
int s;
int e;
int v;
edge(int ss,int ee,int vv){
s = ss;
e = ee;
v = vv;
}
};
vector<edge> vc;//存放所有边
int pre[10010]; //记录前节点
bool cmp(const edge&a,const edge&b){
return a.v < b.v;
}
int Find(int a){ //找根节点
int t = a;
while(pre[t] != t){
t = pre[t];
}
while(pre[a] != t){ //路径压缩
int tt = a;
a = pre[a];
pre[tt] = t;
}
return t;
}
bool merg(int a,int b,int val){ //引入新边 ,返回值是否引入成功
int ta = Find(a);
int tb = Find(b);
if(ta != tb){ //两个节点的根不为同一个,即不会构成环
pre[ta] = tb;
return true;
}
return false;
}
int kruskal(vector<edge> &vc,int n){ //生成最小生成树,返回值为最小生成树值
sort(vc.begin(),vc.end(),cmp);
int te = 0; //边数
int tsum = 0; //权值和
for(int i = 0;i < vc.size();i++){
if(merg(vc[i].s,vc[i].e,vc[i].v)){
te++;
tsum += vc[i].v;
}
}
if(te == n - 1){ //构成生成树了
return tsum;
}
return -1;
}
int main(){
int n;
int m;
cin>>n>>m;
for(int i = 0;i < m;i++){
int a,b,c;
cin>>a>>b>>c;
vc.push_back(edge(a,b,c));
}
for(int i = 1;i <= n;i++){
pre[i] = i;
}
cout<<kruskal(vc,n);
return 0;
}