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 ...
随机推荐
- Html5 学习笔记 【PC固定布局】 实战7 机票预订页面
最终实际效果: HTML代码: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta char ...
- Java并发AtomicReferenceArray类
java.util.concurrent.atomic.AtomicReferenceArray类提供了可以原子读取和写入的底层引用数组的操作,并且还包含高级原子操作. AtomicReference ...
- Spring Cloud 使用Spring Cloud Loadbalancer访问服务地址
获取服务地址 使用的EurekaClient : getNextServerFromEureka() 使用的DiscoveryClient: getInstances() Load Balancer ...
- SQL语句优化方式
不要使用*号进行查询操作,使用具体字段. 索引 在where子句和order by 涉及的字段上合理的添加索引. where 子句优化 避免在where子句中对null值进行判断,应对字段设置默认值 ...
- 11.Container With Most Water (Array; Two-Pointers)
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...
- windows server 2012 R2修改默认远程端口
因客户现场网络复杂,将windows系统的默认远程端口3389归入安全策略中,所以服务器需要修改此端口,配置如下: 首先:登录操作系统,win+R调出运行菜单后输入regedit, 进入注册表编辑相关 ...
- linux上传与下载文件命令
//文件从Linux系统上传到其他系统. sz空格+文件名 //文件从其他系统下载到Linux系统. rz //之后会弹出路径选择框,选择文件,即可下载到当前路径.
- Linux 核心编译与管理
一般情况下,不需要重新编译核心,除非以下特有的用途 [root@localhost ~]# wget ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel ...
- 转帖 java使用poi.3.10读取excel 2010
package poi; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; ...
- 快速加载testNG 的方法
总共两步 首先建包建类建函数,这个是所有项目共同特点,不多少 1.在程序里写@Test,然后就会报错,光标放到那,然后就会有Add TestNG library的提示,点击就会将TestNG的libr ...