- 问题
举一个实例,画出采用Kruskal算法构造最小生成树的过程 - 解析
已知图V = {…} 我们构造一棵最小生成树T
第一步:随意选取起点
第二步:将所有边按权值从小到大的顺序排序
第三步:按顺序遍历每条边(不能构成回路),直到所有节点都被遍历。
原图:
第一步
第二步
第三步
第四步
第五步
第六步
- 设计
伪代码:
for (int i = 0; i < m; i++){
if (e[i].u和e[i].v不在同一连通分量){
把边e[i]加入MST
合并e[i].u和e[i].v所在的连通分量
}
} - 分析
时间复杂度O(mlogm) - 源码
https://github.com/woshichunchongchong/Algorithm_hw/blob/main/Kruskal.cpp
#include
#include
#define MAX_SIZE 1000
using namespace std;
struct Edge{
int u; //点
int v; //点
int w; //权重
}edge[MAX_SIZE];
int flag[MAX_SIZE];
int n;//点数
int m;//边数
int ans;//权值和
int count1;//辅助
//以权重为依据快排
bool cmp(Edge a,Edge b){
return a.w<b.w;
}
int find(int x){
return x==flag[x]?flag[x]:flag[x]=find(flag[x]);
}
//核心算法
void kruskal(){
sort(edge,edge+m,cmp);//将边的权值排序
for(int i=0;i<m;i++){
int uu=find(edge[i].u);
int vv=find(edge[i].v);
if(uu==vv){
continue;
}
ans+=edge[i].w;
flag[vv]=uu;
if(++count1==n-1){
break;
}
}
}
int main(){
cout<<“请输入点数和边数,以空格分隔:”;
cin>>n>>m;
for(int i=1;i<=n;i++){
flag[i]=i;
}
cout<<“请输入边的顶点和权重,以空格分隔:”;
for(int i=0;i<m;i++){
cin>>edge[i].u>>edge[i].v>>edge[i].w;
}
kruskal();
cout<<“最小生成树权值和:”<<ans<<endl;
return 0;
}