Kruskal算法:首先按照边的权值进行从小到大排序,每次从剩余的边中选择权值最小的边且不会产生回路的边加入到生成树中,直到加入n-1条边就结束;
算法难点在与如何判断是否会产生回路。这个可以通过并查集实现,将所有加入生成树的结点加入同一个集合;
代码:
#include <string.h> #include<iostream> #include<vector> #include<queue> #include <algorithm> using namespace std; struct edge{//边的结构 int u; int v; int w; }e[100]; int f[100];//并查集数组 bool compare(struct edge a,struct edge b){//sort函数的比较器,实现边权从小到达排序 return a.w<=b.w; } int getF(int x){//查找结点的根 if(f[x]==x) return x; else { f[x]=getF(f[x]);//直接连接到根结点,实现路径压缩 return f[x]; } } bool unity(int a,int b){//联合所有加入生成树的结点 int f1=getF(a); int f2=getF(b); if(f1!=f2){ f[f1]=f2; return true; } return false; } int main() { int n,m; cin>>n>>m; for(int i=0;i<m;i++){//输入边信息 cin>>e[i].u>>e[i].v>>e[i].w; } for(int i=0;i<100;i++){//初始化并查集 f[i]=i; } sort(e,e+m,compare);//排序 int munber=0,sum=0; for(int i=0;i<m;i++){//从小到大检测每一个结点是否可以加入生成树 if(unity(e[i].u,e[i].v)){ munber++; sum+=e[i].w; } if(munber==n-1) break;//当加入n-1条边,就可以结束 } cout<<sum<<endl; return 0; }