图论 —— 最小生成树 —— Kruskal

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/88625346

【基本思想】

Kruskal 算法基本思想是并查集思想,将所有边升序排序,并认为每一个点都是孤立的,分属 n 个独立的集合。

按顺序枚举每一条边,如果这条边连接的两个点分属两个不同的集合,那么就将这条边加入最小生成树,这两个不同的集合合并为一个集合;如果这条边连接的两个点属于同一集合,那么就跳过。直到选取 n-1条边为止(只剩一个集合)。

其时间复杂度为:O(E*logE),E代表边数。

【算法分析】

以下图为例

开始时,5 个集合{{1},{2},{3},{4},{5}},生成树中没有边,MST=0。

第一次选择 <1,2> 这条边,将边加入生成树中,将两个顶点 1、2 合并为一个集合。

此时,有 4 个集合{{1,2},{3},{4},{5}},1 条边{<1,2>},MST=2。

第二次选择的是 <4,5> 这条边,将这条边加入生成树中,将两个顶点 4、5 合并为一个集合。

此时,有 3 个集合{{1,2},{3},{4,5}},2 条边{<1,2>,<4,5>},MST=5。

第三次选择的是 <3,5> 这条边,将这条边加入生成树中,将它的两个顶点 3、5 所在的两个集合合并为一个集合。

此时,有 2 个集合{{1,2},{3,4,5}},3 条边{<1,2>,<4,5>,<3,5>},MST=11。

第四次选择的是 <2,5> 这条边,将这条边加入到生成树中,将它的两个顶点 2、5 所在的两个集合合并为一个集合。

此时,有 1 个集合{1,2,3,4,5},4 条边{<1,2>,<4,5>,<3,5>,<2,5>},MST=19。

【算法描述】

sort(edge+1,edge+1+m,cmp);//将边按照升序排序
for(int i=1;i<=n;i++)//初始化并查集
    father[i]=i;
int MST=0;//权值和
int k=0;//计数器
for(int i=1;i<=m;i++)//m代表边数
    if(Find(x)!=Find(y))//如果u、v分属两个不同的集合
    {
    	Union(u,v);//合并u、v所在的集合,相当于将边u-v加入最小生成树
        MST+=W(u,v);//最小生成树的权值和加上u-v边的权值
    	k++;//计数器+1,代表存入一个点
    	if(k==n-1)//点数达到n-1个,说明最小生成树已经生成
            break;
    }

猜你喜欢

转载自blog.csdn.net/u011815404/article/details/88625346