Kruskal算法和并查集
Kruskal算法
步骤:
第一步:给所有边按照从小到大顺序排列(直接使用库函数qsort / sort)。
第二步:从小到大依次考察每条边(u,v),在执行第二步时会出现以下两种情况:
情况1:u和v在同一连通分量中,加入(u,v)会形成环,因此不能选择。
情况2:u和v在不同的连通分量中,加入(u,v)就一定是最优的。
伪代码:
(1) 把所有的程序排序,记第i小的边为e[i] (1<=i<m)
(2) 初始化MST为空
(3) 初始化连通分量,让每个点自成一个独立的连通分量
for ( int i = 0; i<m; i++)
if(e[i].u和e[i].v不在一个连通分量)
{
把e[i] 加入MST中
合并e[i].u和e[i].v所在的连通分量
}
分析:
该算法关键点在于“连通分量的查询与合并”——需要知道任意两个点是否在同一个连通分量中,还需要合并两个连通分量。
解决方法:
(1) 暴力求解法:
(2) 使用并查集(Union-Find Set)
代码:(使用并查集方法)
//Kruskal算法
//假设第i条边的两个端点序号和权值分别保存在u[i],v[i]和w[i]中
//排序后第i小的边的序号保存在r[i]中
int cmp(const int i,const int j) //间接排序函数
{return w[i]<w[j];
}
int find(int x) //并查集的find
{return p[x] == x ? x : p[x] = find(p[x]);//如果 p[x] = x,说明x本身是树根,因此返回x;否则返回p[x]的父节点所在树的树根
}
int Kruskal()
{int ans = 0;for(int i = 0;i < n;i++)//初始化并查集p[i]=i;for(int i = 0;i < m;i++)//初始化边序号r[i]=i;sort(r ,r+m ,cmp);//给边排序for(int i = 0; i<m; i++){int e = r[i]; int x = find(u[e]); //找出当前边两个端点所在的集合编号int y = find(v[e]);if(x !=y)//如果在不同集合合并{ans += w[e];p[x] = y;}}}
并查集:(Union-Find Set)
原理:
使用树来表示集合,树的每个节点就表示集合中的一个元素,树根对应的元素就是该集合的代表元(representative).
特点:
每个连通分量看作是一个集合,该集合包含了连通分量的所有点。这些点两两相通,具体的连接方式无关紧要。
基本操作:
- makeSet(s):建立一个新的并查集,其中包含 s 个单元素集合。
- unionSet(x, y):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果相交则不合并。
- find(x):找到元素 x 所在的集合的代表元(即父节点),该操作也可以用于判断两个元素是否位于同一个集合,只要将它们各自的代表比较一下就可以了。
find(x)函数:查找结点x所在树的根节点的递归程序(把x的父节点保存在p[x]中)
int find(int x)
{ p[x] == x ? x : p[x] = find(p[x]);}
如果 p[x] = x,说明x本身是树根,因此返回x;否则返回p[x]的父节点所在树的树根。
特殊情况下:一棵树是一个长长的链,链的最后一个节点为x。
在执行find函数时:每次执行find(x)都会遍历整条链,效率低下。
根据并查集的特点:连通分量中点两两相通,具体的连接方式无关紧要。即树的形态无关紧要。可以做出优化---并查集中的路径压缩
路径压缩:
并查集在每次查找时,令查找路径上的每个节点都直接指向根节点。
Kruskal算法和并查集相关推荐
- Kruskal算法与并查集
Kruskal算法与并查集 一.Kruskal算法 1. 概念 Kruskal算法就是按照图中各个边上的权值大小进行递增排序,以此来构造最小生成树. 2.重点解析 在由Kruskal实现最小生成树的过 ...
- 【算法】并查集的运用
并查集的概念 朋友圈 团伙问题 连通图 总结 并查集的概念 并查集顾名思义就是合并和查找,问题在于合并什么,查找什么.这里有一种朴素的思想来解释这两个问题.就是把这个想成一棵树.合并什么?就是把不在这 ...
- 简单易懂的并查集算法以及并查集实战演练
文章目录 前言 一.引例 二.结合引例写出并查集 1. 并查集维护一个数组 2. 并查集的 并 操作 3. 并查集的 查 操作 4. 基本并查集模板代码实现--第一版(有错误后面分析) 4.1 Jav ...
- 算法总结 — 并查集
参考:算法学习笔记(1) : 并查集 - 知乎 并查集 (disjoint set union) 是 最优美的数据结构之一 合并 (merge): 把两个集合合并 查找 (find): 查找一个元素的 ...
- 算法:并查集(四种方式)
简单并查集 public class UnionFind {private int[] id;private int count;public UnionFind(int N) {count = N; ...
- Java实现_算法_并查集
并查集 作用:用来查找某个图中是否含有闭环. 比如图一: 上图中就是没有闭环的一个图,而下图(图二)就是一个有闭环的图 思路1-数组寻根法: 顾名思义,数组寻根法(自己称呼的)就是寻找每个节点的根节点 ...
- 【算法】并查集刷题总结
目录 P1396 营救 题目描述 "咚咚咚--""查水表!"原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门-- 妈妈下班回家, ...
- python【数据结构与算法】并查集引入
文章目录 1 并查集 2 策略 3 代码 1 并查集 Disjoint Set,实际上字面翻译是不相交的集合. 中文名 "并查集" 实际上源自其基本操作: union(X,Y):求 ...
- 算法(并查集--合并集合)
并查集–合并集合 一共有n个数,编号是1~n,最开始每个数各自在一个集合中. 现在要进行m个操作,操作共有两种: "M a b",将编号为a和b的两个数所在的集合合并,如果两个数已 ...
最新文章
- 制作一个简易的QQ×××
- php-5.2.3.tar.bz2.gz 的解压方法
- REVERSE-PRACTICE-BUUCTF-8
- 启动django服务器报错raise errorclass(errno, errval) django.db.utils.InternalError
- 关于C++中的pow()函数
- mysql 双主 脑裂_MySQL双主(主主)架构方案
- oracle+查表物理块数,查询Oracle表实际物理使用大小
- 扇贝和不背单词_你还没找到中意的背单词APP?我都试过,我来帮你盘点盘点
- SVN客户端安装及使用
- autojs识别数字ocr
- 谷歌引擎html,国内免费使用谷歌翻译引擎
- FFmpeg进行推流的两种方法
- linux安装安卓fastboot,Android的fastboot协议
- 好用用的linux 监控命令
- matlab 定义结构体数组,结构体数组及其定义和使用,C语言结构体数组详解
- 1-3 Python基本数据类型
- Flutter第3天--基础控件(上)
- 环艺考计算机英语吗,应届考取北理环艺分享|愿汗水泪水都不会被辜负!
- ubuntu安装ActiveMQ
- 解决-最新版Google谷歌浏览器谷歌浏览器Chrome一上传或者下载附件图片就未响应卡死