由最小生成树(MST)到并查集(UF)
背景
最小生成树(Minimum Spanning Tree)的算法中,克鲁斯卡尔算法(Kruskal‘s
algorithm)是一种常用算法.
代码
/**
* Created by 浩然 on 4/19/15.
* 快速并查集
* 参考:普林斯顿大学 algorithms 4th edition
*
* 考虑一个问题:
* 一个城市需要将所有的路连起来以保证城市的畅通
* 在开始这个工程前,已经有一些路是连通的了,那么还需要在哪里修多少条路才能用最小的代价完成?
* 由于解决这个问题,只需要知道有多少个连通组件(已经连通的路的集合),
* 所以我们不关心每个连通组件内部的细节(某组件内部路线的布局)。
* 所以我们用并查集(Union-Find)的技术来做.(如果关心细节,比如要给出连通组件的路径,就用DFS技术)
*
* 并查集就像它的名字所述,提供两个操作:
* 1:将给定的点所在的连通组件找出来;
* 2:将两个点连通
*
*/
public class FastUnionFind {
/**
* 父节点集
*/
private int parent[];
/**
* 每个连通组件的大小
*/
private int treeSize[];
/**
* 连通组件的个数
*/
private int componentsCount; public FastUnionFind(int n) {
parent = new int[n];
treeSize = new int[n];
componentsCount = n;
for(int i = 0; i < n; i ++) {
parent[i] = i;
treeSize[i] = 1;
}
} /**
* 连通组件的个数
* @return
*/
public int componentsCount() {
return this.componentsCount;
} /**
* 验证给定编号的界
* @param which
*/
private void validate(int which) {
int n = this.parent.length;
if (which < 0 || which >= n) {
throw new IndexOutOfBoundsException("index which 越界!");
}
} /**
* 找到which属于哪个连通组件
* 意即找出它所在连通组件的代表
*
* @param which 索引或编号
* @return which所在的连通组件的代表
*/
public int find(int which) {
validate(which);
int root = which;
//不断向根回溯
while (root != parent[root]) {
root = parent[root];
} //全路径压缩-效率的关键
//因为我们只关心给定的索引所在组件的根是谁
//所以一个自然的想法就是让所有组件只需要一步就可以找到根
//换句话说,就是让树的高度尽可能的为2
//那么这里既然来到了处理find(which)的上下文,就对它所在的组件进行路径压缩
while (which != root) {
int newParent = parent[which];
parent[which] = root;
which = newParent;
}
return root;
} /**
* 求a、b间是否连通
* @param a 其中一点
* @param b 另一个点
* @return 如果连通返回真,否则返回假
*/
public boolean isConnected(int a,int b) {
//并查的重要意义之一就是测试两点之间是否具有连通性
//自然的,就转化成为它们是否属于同一个连通组件
//这里利用了连通的传递性 x->y,y->z,则x->z
return find(a) == find(b);
} /**
* 将a和b所在的连通组件合并
*
* 意即将a和b连通
*
* @param a 其中一点
* @param b 另一个点
*/
public void union(int a,int b) {
validate(a);
validate(b);
int rootA = find(a);
int rootB = find(b);
//这里利用平衡的思想
//将更小的树挂到更大的树上
if (treeSize[rootA] < treeSize[rootB]) {
parent[rootA] = rootB;
treeSize[rootB] += treeSize[rootA];
} else {
parent[rootB] = rootA;
treeSize[rootA] += treeSize[rootB];
}
//既然合并,连通组件就少了一个
this.componentsCount--;
}
}
由最小生成树(MST)到并查集(UF)的更多相关文章
- 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集
[题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...
- 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)
传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...
- 模板——最小生成树kruskal算法+并查集数据结构
并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...
- 最小生成树(Kruskal)(并查集)
最小生成树 时间限制: 1 Sec 内存限制: 64 MB提交: 11 解决: 2[提交][状态][讨论版] 题目描述 某个宇宙帝国有N个星球,由于宇宙的空间是三维的,因此每个星球的位置可以用三维 ...
- 最小生成树 - 克鲁斯卡尔 - 并查集 - 边稀疏 - O(E * logE)
#define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<cstring> #include<algorithm ...
- 【kruscal】【最小生成树】【并查集扩展】bzoj3714 [PA2014]Kuglarz
ORZ:http://www.cnblogs.com/zrts/p/bzoj3714.html #include<cstdio> #include<algorithm> usi ...
- ACM: 继续畅通工程-并查集-最小生成树-解题报告
继续畅通工程 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Descri ...
- 并查集 (Union-Find Sets)及其应用
定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的 ...
- 【并查集】 不相交集合 - 并查集 教程(文章作者:Slyar)
最近写了一个多星期的并查集,一瞬间贴出这么多解题报告,我想关于并查集的应用先告一段落吧,先总结一下. 在网上看到一篇关于并查集比较好的教程(姑且允许我这么说吧),不转过来是在可惜.献给爱学习的你 文章 ...
随机推荐
- sed实例收集
url:http://blog.csdn.net/hepeng597/article/details/7852468 一.元字符集 1)^锚定行的开始 如:/^sed/匹配所有以sed开头的行. ...
- 随机数生成 && 生成执行锁
生成随机数列: openssl rand -base64 uuidgen echo $RANDOM | md5sum echo $RANDOM | sha256sum 随机小写10个字母 随机数: [ ...
- 记录一下mariadb设置主从同步的过程[虚拟机测试]
背景:因为工作的关系,需要找寻实时同步数据到另外系统的服务器的数据库上,查询下来,用mariadb进行跨服务器的同步数据动作,用主从同步比较多,也比较保险 也有使用shell脚本的,定时定候的执行my ...
- Python模块:Random(未完待续)
本文基于Python 3.6.5的官文random编写. random模块简介 random为各种数学分布算法(distributions)实现了伪随机数生成器. 对于整数,是从一个范围中均匀选择(u ...
- 数据库-mysql储存过程
存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行. 一:创建存储过程 MariaDB [test2]> delimiter // MariaDB [tes ...
- 洛谷P2312解方程
传送门 思路分析 怎么求解呢? 其实我们可以把左边的式子当成一个算式来计算,从1到 $ m $ 枚举,只要结果是0,那么当前枚举到的值就是这个等式的解了.可以通过编写一个 $ bool $ 函数来判断 ...
- SSIS 学习之旅 序章 和 简介
SSIS 学习之旅目录: 第一章: SSIS 学习之旅 第一个SSIS 示例(一) 第二章: SSIS 学习之旅 第一个SSIS 示例(二) 第三章: SSIS 学习之旅 数据同步 第四章: SSIS ...
- PHP的单引号和双引号
单引号内部的变量不会执行,双引号会执行. <?php $name = 'hello php'; echo "<h1>$name</h1>"; echo ...
- linux 添加samba账户
1.adduser kilen 添加linux账户 2.cd /etc/samba/ 当前目录下修改smb.conf 文件 ,一般情况下是只读文件,需要修改权下 (用root用户) chmod 7 ...
- 个人博客www.0x002.com
cnblogs只是相当于一个备份,感兴趣的读者赏脸关注下.