标签:int Kruskal 最小 生成 算法 edges include
与Prim算法贪心选择不同,Kruskal算法采取每次选择权值最小的边的方法,这样,在不构成环且最后能够连接完所有边它们的权重和一定是最小的。
和之前Prim算法的图一样,便于区别二者。
Kruskal既然是选择最小的边,那么就先找一个最小的出来,是1-6(10)
然后继续找出剩下的边中最小一条边,是3-4(12)
继续找一条最小的出来,2-7(14)
在来,为了区别已经选择的点,我把点的颜色也做个标记,有颜色的表示为已经加入生成树的点
喔,忘了把最小的边2-3(16)选了
现在图变成了这样,(依旧难看).......
还没找完,继续找最小的边..是7-4(18)
你会发现我把这条边用蓝色标记了,是不是我为了好玩??当然不是了,这条边是有问题的。
这条边虽然是上一次选择完后剩下的边中最短的,但是,它的左右两个点已经是最小生成树的结点了,而把这条边加入后,构成了右边的一个大大的环。这样显然不是最小生成树了.
再复习下,生成树:一个连通图的生成树,是一个极小连通子图,其中包含图的所有结点,和构成一棵数的(n-1)条边。如果在一棵生成树的两个结点上添加任意一边,必定构成一个环。
最小生成树:图的所有生成树中所有边的权值和最小的那个生成树。
所以,有环的连生成树都不是了,怎么会是最小生成树。。
所以,这条边7-4(18)丢掉丢掉,重新选择。选择5-4(22)
好像图中所有的点都有颜色了,但是还没完全好,因为它们还不是一条绳上的蚂蚱,
继续选,最短的是6-5(25)
继续选 ,唉,不对,选了24发现又有环了,选28也构成环了。。。。在仔细一看,最小生成树已经生成了
即
这个就是Kruskal算法的流程。那么接下来说说代码。
1 struct node 2 { 3 int u; 4 int v; 5 int w;//边的权重 6 }Edge; 7 void Kruskal(Graph g)//无向图g采用邻接矩阵 8 { 9 Edge E[MAXN];//存放图中所有的边 10 int vest[MAXN];//辅助数组,存放连通的点的编号 11 k = 0; 12 for(int i = 0;i < g.n;i++) 13 { 14 for(int j = 0; j <= i ;j++) 15 { 16 if(g.egdes[i][j] != 0 &&g.egdes[i][j]!= INF) 17 {//说明i到j边 18 E.[k].u = i; 19 E.[k].v = j; 20 E.[k].w = g.edges[i][j]; 21 k++; 22 } 23 } 24 }//以上将所有的边都加入到E数组中,肯定是不重复的 25 Sort(E);//对边集数组进行排序。 26 Init(vest);//将辅助数组初始化,即每个结点一开始都没有加入到最小生成树中,所以它们各自为一个阵营 27 j = 0; 28 Count = 0 ; 29 while(Count < g.n)//已经加入生成树的结点数小于图的结点数,表明生成树没生成完, 30 { 31 u1 = E[j].u; 32 v1 = E[j].v;//选出最短的边 33 s1 = vest[u1]; 34 s2 = vest[v1];//得到两个所在集合的编号, 35 if(s1 != s2)//如果它们编号不等,,说明它们还每加入到同一个生成树中, 36 { 37 //这里可以打印它们的编号 。。。 38 k++; 39 for(int i = 0; i< g.n;i++) 40 { 41 if(vest[i]==s2) 42 { 43 vest[i] = s1;//把属于s2的那个点加入到s1所在点集合中 44 }//即合并到一起去,表明它们在一个生成树中了,这样就和 45 //其他没有加入到的点区分开了 46 } 47 } 48 j++;//继续找下一条边 49 } 50 }View Code
这个代码没有写全,因为这样用的次数少的可怜了。都用它的升级版了
首先,针对排序的问题,排序随你选,接下来就是判断是否构成环的问题了。这里用并查集轻易的实现
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 #include<stack> 7 #include<map> 8 #include<set> 9 #include<list> 10 #include<queue> 11 #include<string> 12 #include<algorithm> 13 #include<iomanip> 14 using namespace std; 15 const int maxn = 100; 16 int par[maxn]; 17 int rank[maxn]; 18 int n; 19 int m; 20 21 struct node 22 { 23 int Start; 24 int End; 25 int weight; 26 }edges[maxn]; 27 28 int cmp(node a,node b)//按权值从小到大排序 29 { 30 return a.weight < b.weight; 31 } 32 33 void Init(int n)//par初始化为自己 34 { 35 for(int i = 1;i <= n;i++) 36 { 37 par[i] = i; 38 } 39 } 40 int Find(int x)//找出父亲结点 41 { 42 if(x != par[x])return x =Find(par[x]); 43 return x; 44 } 45 46 int Kruskal() 47 { 48 int sum = 0; 49 for(int i = 1;i <= m ;i++) 50 { 51 int a = Find(edges[i].Start); 52 int b = Find(edges[i].End); 53 if(a != b)//父亲结点不同 54 { 55 sum += edges[i].weight;//一般求最小生成树的长度,这里就没去掉 56 par[a] = b;//合并集合 57 } 58 } 59 return sum; 60 } 61 62 int main() 63 { 64 65 cin>>n>>m; 66 Init(n); 67 for(int i = 1;i <= m;i++) 68 { 69 cin>>edges[i].Start>>edges[i].End>>edges[i].weight; 70 } 71 sort(edges+1,edges+1+n,cmp); 72 cout<<Kruskal(); 73 return 0; 74 }View Code
标签:int,Kruskal,最小,生成,算法,edges,include 来源: https://www.cnblogs.com/ygsworld/p/11256505.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。