一、用Kruskal算法求最小生成树
基本算法紫书上写的比较详细了,自己理解的话,核心操作就是两步,第一步排序,第二步按照所排顺序连边,这里的排序方式是按照边权由小到大排,连边方式是选不会使得已有部分成环的边,也就是起点和终点不在一个连通分量的边。
二、代码及注释
这里的并查集部分之间搬了之前自己的并查集有关博客的代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
//const int maxn=5005;
const int maxn=400005;
int pa[maxn],r[maxn];
int n,m,p;
int findy(int x){
return pa[x]==x?x:pa[x]=findy(pa[x]);
}
bool pd(int x,int y){
return (findy(x)==findy(y));
}
void uni(int x,int y){
int xx=findy(x);
int yy=findy(y);
if(xx!=yy){
if(r[xx]>r[yy]) swap(xx,yy);
else if(r[xx]==r[yy]) r[xx]++;
pa[xx]=yy;
r[yy]+=r[xx];
}
}
int sum=0; //表示被连通的数目,数目达到n+1即可
struct edge{
int from;
int to;
int dist;
edge(int x,int y,int d):from(x),to(y),dist(d){}
};
vector<edge> a;
bool cmp(edge xx,edge yy){
return xx.dist<yy.dist;
}
int ans=0;
int main(){
cin>>n>>m;
int x0,y0,w0;
for(int i=0;i<=n;i++) pa[i]=i;
for(int i=0;i<m;i++){
cin>>x0>>y0>>w0;
a.push_back(edge(x0,y0,w0));
}
sort(a.begin(),a.end(),cmp);
for(int i=0;i<m;i++){
int xx=a[i].from; //遍历每条边并存储一下边的起点和终点
int yy=a[i].to;
if(!pd(xx,yy)){
uni(xx,yy);
ans+=a[i].dist;
}
}
cout<<ans;
return 0;
}
来源:CSDN
作者:耦台
链接:https://blog.csdn.net/numb_ac/article/details/103717709