kruskal算法【最小生成树2】
设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】的更多相关文章
- Kruskal算法-最小生成树
2017-07-26 10:32:07 writer:pprp Kruskal算法是根据边的加权值以递增的方式,一次找出加权值最低的边来建最小生成树:并且每次添加的边不能造成生成树有回路,直到找到N ...
- POJ-2349(kruskal算法+最小生成树中最大边的长度)
Arctic POJ-2349 这题是最小生成树的变形题目.题目的意思是已经有s个卫星频道,这几个卫星频道可以构成一部分的网络,而且不用费用,剩下的需要靠d的卫星接收器.题目要求的就是最小生成树中,最 ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- 最小生成树的Kruskal算法实现
最近在复习数据结构,所以想起了之前做的一个最小生成树算法.用Kruskal算法实现的,结合堆排序可以复习回顾数据结构.现在写出来与大家分享. 最小生成树算法思想:书上说的是在一给定的无向图G = (V ...
- 最小生成树——kruskal算法
kruskal和prim都是解决最小生成树问题,都是选取最小边,但kruskal是通过对所有边按从小到大的顺序排过一次序之后,配合并查集实现的.我们取出一条边,判断如果它的始点和终点属于同一棵树,那么 ...
- 贪心算法-最小生成树Kruskal算法和Prim算法
Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...
- Prim算法和Kruskal算法(图论中的最小生成树算法)
最小生成树在一个图中可以有多个,但是如果一个图中边的权值互不相同的话,那么最小生成树只可能存在一个,用反证法很容易就证明出来了. 当然最小生成树也是一个图中包含所有节点的权值和最低的子图. 在一个图中 ...
- 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)
matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include < ...
- 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind
最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...
- 最小生成树Kruskal算法
Kruskal算法就是把图中的所有边权值排序,然后从最小的边权值开始查找,连接图中的点,当该边的权值较小,但是连接在途中后会形成回路时就舍弃该边,寻找下一边,以此类推,假设有n个点,则只需要查找n-1 ...
随机推荐
- apt-cyg for Cygwin(setup-x86_64 .exe )在win10下的安装
cygwin安装后,如果没有选择安装所有包(这会占用5G空间,很多包不需要),再需要安装新的包,可以启动setup-x86_64 .exe(我把它放置在C:\cygwin64目录下),添加包(如wge ...
- Yahoo34条军规——雅虎WEB前端网站优化
雅虎给出了优化网站加载速度的34条法则(包括Yslow规则22条) 详细说明,下载转发 ponytail 的译文(来自帕兰映像). 1.Minimize HTTP Requests 减少HTTP请求 ...
- 【读书笔记】:MIT线性代数(3):Special Solution, Rank and RREF
Special Solutions: Notice what is special about s 1 and S2. They have ones and zeros in the last two ...
- Springboot集成Mybatis+PageHelper
1.Springboot项目引入mysql和mybatis的依赖: <dependency> <groupId>org.mybatis.spring.boot</grou ...
- Java_3.Java帮助文档
1.Oracle的在线帮助文档 http://docs.oracle.com/javase/8/docs/api 2.jdk源码内容(包含5个部分) [以下内容参考至:https://blog.csd ...
- 【知识强化】第四章 网络层 4.3 IP
这节课我们来学习一下IP数据报的格式.那之所以把路由算法这一小节跳过呢,就是因为我们之后会要讲到路由的选择协议.那在路由选择协议这一块讲路由算法,我觉得是比较合适的.那我们先来看一下这节课要讲的知识. ...
- 【转载】MySQL查询当天0点,昨天时间
转载自:https://blog.csdn.net/qq_22158021/article/details/78800299 今天是 SELECT NOW();-- 2015-09-28 13:48: ...
- Linux 核心编译与管理
一般情况下,不需要重新编译核心,除非以下特有的用途 [root@localhost ~]# wget ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel ...
- PostgreSQL的学习-序列
序列对象(也叫序列生成器)都是用CREATE SEQUENCE创建的特殊的单行表.一个序列对象通常用于为行或者表生成唯一的标识符.下面序列函数,为我们从序列对象中获取最新的序列值提供了简单和并发读取安 ...
- HTML+CSS+JS是什么
html:整合网页结构和内容显示的一种语言 css:是一种用来表现HTML或XML等文件样式的计算机语言 js:增加表现力的脚本 做网页前台设计的标准套装,html是一些网页控件,css是美化这些控件 ...