标签:return int Kruskal father 最小 生成 算法 权值 root
介绍:Kruskal算法是用来求加权连通图的最小生成树的一种算法。
对于一个图来说,我们可以选择不同的边而产生不同的树,由于边的选择不一样,每一条边的权值不一样,那我们最后生成出来的树的权值也就不一样,Kruskal算法就是来找怎样选择边才可以使产生的树的权值最小。
思路:现在有一个集合Q,来表示图中的所有的点,有一个集合U,来表示已经生成树中的点,当我们选择了一条边,那我们就将这条边的两个顶点加入到U中,初始时有n个点,m条边。既然我们要求的是生成的树的权值最小,那么我们是不是可以依次选择图中的最小边呢?由于一共用n个点,m条边,那么我们要选的边的最小的个数就是n-1。按照这样的思路,那我们首先要做的就是将这m条边进行从小到大排序,我们只要依次选择这些排好序的边就可以了,当我们已经将某个点已经加入到了我们生成树中,我们就不选择这条边。那么问题就来了,怎样来判断某个点是否已经加入到生成树中?这个时候我们可以使用并查集来判断这个点是否已经加入到了生成树中。 关于并查集:https://www.cnblogs.com/zhoubo123/p/11709160.html
代码实现:
#include<iostream> #include<algorithm> using namespace std; int father[1000000]; struct node { int a;//两个顶点 int b; int w;//权值。 }; int find(int root)//并查集查找函数 { if(root!=father[root]) father[root]=find(father[root]);//路径压缩。 return father[root]; } int merge(int a,int b)//并查集合并函数 { int aa=find(a); int bb=find(b); if(aa!=bb) { father[bb]=aa; return 1;//能够合并返回1 } return 0;//不能够合并返回0 } bool cmp(node a,node b)//排序 { return a.w<b.w; } int main() { int n,m; cin>>n>>m; node A[m]; int cnt=0;//记录选择边的个数 。 int sum=0;//生成树的权值。 for(int i=0;i<=n;i++) father[i]=i;//初始化并查集 。 for(int i=0;i<m;i++) cin>>A[i].a>>A[i].b>>A[i].w; sort(A,A+m,cmp);//排序 for(int i=0;i<m;i++)//最小生成树主体。 { if(merge(A[i].a,A[i].b))//能够合并那么久选择这条边 。 { sum+=A[i].w; cnt++; } if(cnt==n-1)//生成树中有n-1个点时,选择完成 。 break; } cout<<n-1<<" "<<sum;//输出最小生成树的权值。 return 0; }
标签:return,int,Kruskal,father,最小,生成,算法,权值,root 来源: https://www.cnblogs.com/zhoubo123/p/11788425.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。