设G=(V,E)是无向连通带权图,V={1,2,…,n};

设最小生成树T=(V,TE),该树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),Kruskal算法将这n个顶点看成是n个孤立的连通分支。

它首先将所有的边按权值从小到大排序,然后只要T中选中的边数不到n-1,就做如下的贪心选择:

在边集E中选取权值最小的边(i,j),如果将边(i,j)加入集合TE中不产生回路(圈),则将边(i,j)加入边集TE中,即用边(i,j)将这两个连通分支合并连接成一个连通分支;

否则继续选择下一条最短边。把边(i,j)从集合E中删去。

继续上面的贪心选择,直到T中所有顶点都在同一个连通分支上为止。

此时,选取到的n-1条边恰好构成G的一棵最小生成树T。

那么,怎样判断加入某条边后图T会不会出现回路呢?

该算法对于手工计算十分方便,因为用肉眼可以很容易看到挑选哪些边能够避免构成回路(避圈法),但使用计算机程序来实现时,还需要一种机制来进行判断。

Kruskal算法用了一个非常聪明的方法,就是运用集合避圈:

如果所选择加入的边的起点和终点都在T的集合中,那么就可以断定一定会形成回路(圈)。其实就是我们前面提到的“避圈法”:边的两个结点不能属于同一集合。

步骤1:初始化。将图G的边集E中的所有边按权值从小到大排序,边集TE={},把每个顶点都初始化为一个孤立的分支,即一个顶点对应一个集合。

步骤2:在E中寻找权值最小的边(i,j)。

步骤3:如果顶点i和位于两个不同连通分支,则将边(i,j)加入边集TE,并执行合并操作,将两个连通分支进行合并【即两个顶点设置成同一个集合号,一般向小集合号合并】。

步骤4:将边(i,j)从集合E中删去,即E=E-{(i,j)}。

步骤5:如果选取边数小于n-1,转步骤2;否则,算法结束,生成最小生成树了。

适用范围:要求无向图

kruskal算法(读者可以将其读作“克鲁斯卡尔算法”同样是解决最小生成树问题的一个算法。和prim算法不同,kruskal算法采用了边贪心的策略,其思想极其简洁,理解难度比prim算法要低很多。

kruskal算法的基本思想为:在初始状态时隐去图中的所有边,这样图中每个顶点都自成一个连通块。

之后执行下面的步骤:

①对所有边按边权从小到大进行排序。

②按边权从小到大测试所有边,如果当前测试边所连接的两个顶点不在同一个连通块中,则把这条测试边加入当前最小生成树中;否则,将边舍弃。

③执行步骤②,直到最小生成树中的边数等于总顶点数减1或是测试完所有边时结束。

而当结束时如果最小生成树的边数小于总顶点数减1,说明该图不连通。

接下来以图10-51a为例,给出对该图执行kruskal算法的步骤。

①当前图中边权最小的边为V。V,权值为1。由于Vo和V4在不同的连通块中,因此把边VoVa加入最小生成树中,此时最小生成树中有1条边,权值之和为1,如图10-51所示。

因此,kruskal算法的思想简单说来就是:

每次选择图中最小边权的边,如果边两端的顶点在不同的连通块中,就把这条边加入最小生成树中。

 //边集定义部分
struct edge
{
int u,v;//边的两个端点编号
int cost;//边权
}E[MAXE];//最多有MAXE条边 bool cmp(edge a,edge b)
{
return a.cost <b.cost;
} //并查集部分
int father[MAXV];//并查集数组
int findFather(int x)
{//并查集查询函数
int a=x;
while(x!=father[x])
x=father[x];
//路径压缩
while(a!=father[a])
{
int z = a;
a = father[a];
father[z]=x;
}
return x;
} //kruskal部分,返回最小生成树的边权之和,参数n为顶点个数,m为图的边数
int kruskal(int n,int m)
{//ans为所求边权之和,Num Edge为当前生成树的边数
int ans=,Num Edge=;
for(int i=;i<n;i++)//顶点范围是[0,n-1]
father[i]=i;//并查集初始化
sort(E,E+m,cmp);//所有边按边权从小到大排序
for(int i=;i<m;i++)
{//枚举所有边
int faU=findFather(E[i].u);//查询测试边两个端点所在集合的根结点
int faV=findFather(E[i].v);
if(faU!=faV)
{//如果不在一个集合中
father[faU]=faV;//合并集合(即把测试边加入最小生成树中)
ans += E[i].cost;//边权之和增加测试边的边权
Num_Edge++;//当前生成树的边数加1
if(Num_Edge == n-)
break;//边数等于顶点数减1时结束算法
}
}
if(Num_Edge!=n-)
return -;//无法连通时返回-1
else
return ans;//返回最小生成树的边权之和
}

kruskal算法【最小生成树2】的更多相关文章

  1. Kruskal算法-最小生成树

    2017-07-26  10:32:07 writer:pprp Kruskal算法是根据边的加权值以递增的方式,一次找出加权值最低的边来建最小生成树:并且每次添加的边不能造成生成树有回路,直到找到N ...

  2. POJ-2349(kruskal算法+最小生成树中最大边的长度)

    Arctic POJ-2349 这题是最小生成树的变形题目.题目的意思是已经有s个卫星频道,这几个卫星频道可以构成一部分的网络,而且不用费用,剩下的需要靠d的卫星接收器.题目要求的就是最小生成树中,最 ...

  3. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  4. 最小生成树的Kruskal算法实现

    最近在复习数据结构,所以想起了之前做的一个最小生成树算法.用Kruskal算法实现的,结合堆排序可以复习回顾数据结构.现在写出来与大家分享. 最小生成树算法思想:书上说的是在一给定的无向图G = (V ...

  5. 最小生成树——kruskal算法

    kruskal和prim都是解决最小生成树问题,都是选取最小边,但kruskal是通过对所有边按从小到大的顺序排过一次序之后,配合并查集实现的.我们取出一条边,判断如果它的始点和终点属于同一棵树,那么 ...

  6. 贪心算法-最小生成树Kruskal算法和Prim算法

    Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...

  7. Prim算法和Kruskal算法(图论中的最小生成树算法)

    最小生成树在一个图中可以有多个,但是如果一个图中边的权值互不相同的话,那么最小生成树只可能存在一个,用反证法很容易就证明出来了. 当然最小生成树也是一个图中包含所有节点的权值和最低的子图. 在一个图中 ...

  8. 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)

    matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include < ...

  9. 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

    最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...

  10. 最小生成树Kruskal算法

    Kruskal算法就是把图中的所有边权值排序,然后从最小的边权值开始查找,连接图中的点,当该边的权值较小,但是连接在途中后会形成回路时就舍弃该边,寻找下一边,以此类推,假设有n个点,则只需要查找n-1 ...

随机推荐

  1. JS 提取公式中的参数

    'A+B-C/D*E'.split(/[*/()+-]/)  => [A,B,C,D,E]

  2. Html5 学习笔记 --》html基础 css 基础

    HTML5 功能 HTML5特点 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta cha ...

  3. C# 笔记 获取程序当前目录

    在C#中,我们有以下几种方式获取程序当前目录: Console.WriteLine(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssem ...

  4. python面试如何以相反顺序展示一个文件的内容?

    >>> for line in reversed(list(open('Today.txt'))): print(line.rstrip())containeritertools D ...

  5. 超強的Linux指令解釋網站《explainshell.com》,學Linux必備!

    ExplainShell 官方網站:http://explainshell.com/ 原始碼下載:https://github.com/idank/explainshell 用瀏覽器打該explain ...

  6. 【ARC076F】 Exhausted

    hall定理大概是匈牙利的理论基础吧 hall定理的内容:二分图\(G\)的的左部点点集为\(\rm X\),右部点点集为\(\rm Y\),设\(|\rm X|\leq |Y|\),则二分图\(G\ ...

  7. MVC的实体模型写在类库,为什么被其他类库调用时,用不了模型的表?

    一,很简单,由于第一次添加实体模型时,VS会自动帮你添加引用System.Data.Entity到当前类库,如下图示: 二,而手动添加的类库并不存在这个引用,则及时你引用了当前的实体模型的类库,却使用 ...

  8. WPFの触发器详解

    例子1 简单触发器Triggers——满足简答的条件,触发 <Window x:Class="Styles.SimpleTriggers" xmlns="http: ...

  9. node单线程

    const fs=require('fs'); console.time('timer'); fs.stat('./1.txt',(err,stats)=>{ //console.log(sta ...

  10. 四、附加到进程调试(.NET Framework)

    附加到进程调试: 1.需要在IIS配置环境并可运行即通过浏览器可打开. 2.找到项目w3wp.exe进程并附加到进程调试,点击项目添加断点,直接访问浏览器即可. 优点:w3wp.exe是已经运行的,调 ...