背景

最小生成树(Minimum Spanning Tree)的算法中,克鲁斯卡尔算法(Kruskal‘s
algorithm)是一种常用算法.

在克鲁斯卡尔算法中的一个关键问题是如何判断图中的两个点是否形成环(cycle),那么一种高效的判断方式就是使用并查集技术(Union-Find).

代码

/**
* 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)的更多相关文章

  1. 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

    [题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...

  2. 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)

    传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...

  3. 模板——最小生成树kruskal算法+并查集数据结构

    并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...

  4. 最小生成树(Kruskal)(并查集)

    最小生成树 时间限制: 1 Sec  内存限制: 64 MB提交: 11  解决: 2[提交][状态][讨论版] 题目描述 某个宇宙帝国有N个星球,由于宇宙的空间是三维的,因此每个星球的位置可以用三维 ...

  5. 最小生成树 - 克鲁斯卡尔 - 并查集 - 边稀疏 - O(E * logE)

    #define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<cstring> #include<algorithm ...

  6. 【kruscal】【最小生成树】【并查集扩展】bzoj3714 [PA2014]Kuglarz

    ORZ:http://www.cnblogs.com/zrts/p/bzoj3714.html #include<cstdio> #include<algorithm> usi ...

  7. ACM: 继续畅通工程-并查集-最小生成树-解题报告

    继续畅通工程 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Descri ...

  8. 并查集 (Union-Find Sets)及其应用

    定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的 ...

  9. 【并查集】 不相交集合 - 并查集 教程(文章作者:Slyar)

    最近写了一个多星期的并查集,一瞬间贴出这么多解题报告,我想关于并查集的应用先告一段落吧,先总结一下. 在网上看到一篇关于并查集比较好的教程(姑且允许我这么说吧),不转过来是在可惜.献给爱学习的你 文章 ...

随机推荐

  1. BigDecimal常用方法

    一.介绍 Java中提供了大数字(超过16位有效位)的操作类,即 java.math.BinInteger 类和 java.math.BigDecimal 类,用于高精度计算. 其中 BigInteg ...

  2. java 内部类可以被覆盖吗

    如果创建了一个内部类,然后继承其外围类并重新定义内部类时,"覆盖"内部类就好像是其外围类的一个方法,并不起作用, 这两个内部类是完全独立的两个实体,各自在自己的命名空间内 //: ...

  3. Centos之常见目录作用介绍

    我们先切换到系统根目录 / 看看根目录下有哪些目录 [root@localhost ~]# cd / [root@localhost /]# ls bin   dev  home  lib64  mn ...

  4. linux 系统网卡无法识别,缺少驱动

    #linux网卡驱动安装# Linux设备加载 #lsmod Module Size Used by e1000e 查看硬件设备 ls /usr/share/hwdata 查看pci网卡设备 lspc ...

  5. java批量生成excel文件

    1.导入用于操作excel的jar,地址:https://pan.baidu.com/s/1qXADRlU 2.生成excel使用的模版文件,地址:https://pan.baidu.com/s/1c ...

  6. 涨姿势系列之——内核环境下花式获得CSRSS进程id

    这个是翻别人的代码时看到的,所以叫涨姿势系列.作者写了一个获取CSRSS进程PID的函数,结果我看了好久才看懂是这么一个作用.先放上代码 HANDLE GetCsrPid() { HANDLE Pro ...

  7. Hive SQL综合案例

    一 Hive SQL练习之影评案例 案例说明 现有如此三份数据:1.users.dat 数据格式为: 2::M::56::16::70072, 共有6040条数据对应字段为:UserID BigInt ...

  8. keras Variable set_value错误解决

    问题: 如: from keras import backend as K varib = K.variable(0.) new_value = np.min([0.1, 1.0]) varib.se ...

  9. 【LOJ】#2040. 「SHOI2015」零件组装机

    题解 我写的应该有bug但是我懒得改了 就是最后一次合并的n要么是0点边集的最后一条边,要么是0点边集最后两条边的差,我们分别拎出来判断一下哪个可行(也许两个都可行,但是我不想多做修改了--) 然后递 ...

  10. Hadoop基准测试

    其实就是从网络上copy的吧,在这里做一下记录 这个是看一下有哪些测试方式: hadoop  jar /opt/cloudera/parcels/CDH-5.3.6-1.cdh5.3.6.p0.11/ ...