原理:使用贪心算法。先将所有边按照权值从小到大排序,每个点初始都是一个树(一个节点的树)。从前到后遍历边集,对于当前边x-y来说,如果x、y已经在我们的最小生成树里,那么跳过该边。
如果x、y至少有一个不在我们的最小生成树里,将该边加入最小生成树,并且将包含x的树和包含y的树合并为一棵树。(使用并差集的合并操作完成)
注:代码未验证正确性!
//Kruscal算法 2020年3月29日 21:41:19 //---------------------------------- vector<int> father; //并差集 void merge(int x,int y){ int x_father=get_father(x),y_father=get_father(y); father[x]=y_father; } int get_father(int x){ if(father[x]!=x){ return father[x]=get_father(father[x]); } return x; } //----------------------------------- struct edge //有权边 { int point1; int point2; int weigh; edge(int x,int y,int z):point1(x),point2(y),weigh(z){} }; //----------------------------------- //求带权无向图的MST边权和 int Kruscal(){ int points;//points:点数 cout<<"输入点个数:"<<endl; cin>>points; father.resize(points); for(int i=0;i<points;++i){ father[i]=i; } vector<edge> edges; //edges:有权边的集合 int r,s,t; while(cin>>r>>s>>t){ edges.emplace_back(r,s,t); } sort(edges.begin(),edges.end(),[](const edge& a,const edge& b){return a.weigh<b.weigh;}); //按照权从小到大排序 int res; //MST的权和 int edge_cnt=0; //已经选入的边数 for(const auto& edge:edges){ int p1=edge.point1,p2=edge.point2; if(father[p1]==father[p2]){//p1、p2已经加入MST continue; } res+=edge.weigh;//该边加入MST ++edge_cnt; merge(p1,p2);//合并两个点 if(edge_cnt>=points-1){//边数为点数-1时,完成了MST的构建 break; } } return res; }