并查集

并查集处理的是集合之间的关系,即‘union' , 'find' 。在这种数据类型中,N个不同元素被分成若干个组,每组是一个集合,这种集合叫做分离集合。并查集支持查找一个元素所属的集合和两个元素分别所属的集合的合并。

并查集支持以下操作:

MAKE(X):建立一个仅有成员X的新集合。

UNION(X,Y):将包含X和Y的动态集合合并为一个新集合S,此后该二元素处于同一集合。

FIND(X):返回一个包含X的集合。

注意:并查集只能进行合并操作,不能进行分割操作。

并查集的实现原理

并查集是使用树结构实现的:

1.初始化:准备N个节点来表示N个元素,最开始没有边。

2.合并:从一个组的根向另一个组的根连边,这样两棵树就变为了一棵树,也就把两个组合并为一个组了。

3.查询:查询两个节点是否在同一个组,只需要查询他们是否具有相同的根。

注意:

(1) 为避免树的退化,对于每棵树,记录其高度rank。

(2) 如果合并时两棵树高度不同,那么从rank小的向rank大的连边。

(3) 对于每个节点,一旦向上走到了一次根节点,就把这个节点到父亲的边改为直接连向根。不仅指查询的节点,也包括查询过程中经过的节点。使用这种简化的方法时,即使树的高度发生了改变,我们也不修改rank值。

并查集的复杂度

对N个元素并查集进行的一次操作的复杂度是O(α(N)),α(N)是阿克曼函数的反函数。这个复杂度是比O(LogN)还要快的。

并查集的具体C++实现:

#pragma once
#include <cstring>
const int MAX_N = ;
class unite_find_set
{
private:
int par[MAX_N];
int rank[MAX_N];//增加rank变量来防止树的退化(尽量让层数低的树连接到层数高的树上)
public:
unite_find_set(int n = )
{
init(n);
}
void init(int n)
{
for (int i = ;i < n;++i)
{
par[i] = i;
rank[i] = ;
}
}
int find(int x)
{
if (par[x] == x) return x;
//此部分为两部分,find(par[x])为回溯寻找根节点,par[x]=回溯结果是把
//叶子节点直接连接到根节点上以实现路径压缩,为简化起见,路径压缩后
//我们没有更改rank值
else return par[x] = find(par[x]);
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y) return;
if (rank[x] < rank[y]) par[x] = y;
else
{
par[y] = x;
if (rank[x] == rank[y]) rank[x]++;
}
}
bool same(int x, int y)
{
return find(x) == find(y);
}
}

并查集的应用实例

(因为本人太懒,以下代码并未输入数据测试,但我有迷之自信没有问题)

更新:果然是迷之自信,已经发现问题了,已修复。

Kruskal最小生成树生成法:

Kruskal算法的简述见Prime算法的简述这篇文章有简单说明。

#include <algorithm>
#include "union_find_set.h"
const int MAX_V = ;
const int INF = ;
int cost[MAX_V][MAX_V];
int d[MAX_V], V;
struct Edge
{
int from, to, cost;
} edge[MAX_N];//用结构体表示边
bool compare(const Edge &a, const Edge &b)
{
return a.cost < b.cost;
}
bool path[MAX_V][MAX_V];//记录结果
int res;
void Kruskal()
{
res = ;
union_find_set set(V);//初始化并查集
int p = ;//初始化edge数组游标
for (int i = ;i < V;++i)
{
for (int j = ;j < V;++j)
{
path[i][j] = false;//给结果数组赋值
if (cost[i][j] != INF)
{
edge[p++] = { i,j,cost[i][j] };//给edge数组赋值
}
}
}
std::sort(edge, edge + p, compare);//按边权从小到大排序edge数组
for (int i = ;i < p;++i)
{
if (!set.same(edge[i].from, edge[i].to))//如果边的首尾节点没有在一个生成树中
{
path[edge[i].from][edge[i].to] = true;//添加这条边进入生成树
set.unite(edge[i].from, edge[i].to);//让首尾节点连接
res += edge[i].cost;
}
}

并查集(union-find set)与Kruskal算法的更多相关文章

  1. 并查集(Union/Find)模板及详解

    概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...

  2. POJ 1611 The Suspects 并查集 Union Find

    本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每 ...

  3. Java 并查集Union Find

    对于一组数据,主要支持两种动作: union isConnected public interface UF { int getSize(); boolean isConnected(int p,in ...

  4. 最小生成树(Minimum Spanning Tree)——Prim算法与Kruskal算法+并查集

    最小生成树——Minimum Spanning Tree,是图论中比较重要的模型,通常用于解决实际生活中的路径代价最小一类的问题.我们首先用通俗的语言解释它的定义: 对于有n个节点的有权无向连通图,寻 ...

  5. POJ1182食物链(并查集经典好题)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66964#problem/E 题目思路:主要有两种思路:1.带权并查集2.挑战程 ...

  6. bzoj1854 [Scoi2010]游戏【构图 并查集】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1854 没想到怎么做真是不应该,看到每个武器都有两个属性,应该要想到连边构图的!太不应该了! ...

  7. NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并

    思路: Kruskal求最大生成树+倍增LCA // by SiriusRen #include <cstdio> #include <cstring> #include &l ...

  8. 图-连通分量-DFS-并查集-695. 岛屿的最大面积

    2020-03-15 16:41:45 问题描述: 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二 ...

  9. 并查集 & 最小生成树详细讲解

    并查集 & 最小生成树 并查集 Disjoint Sets 什么是并查集?     并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将 ...

  10. [leetcode] 并查集(Ⅰ)

    预备知识 并查集 (Union Set) 一种常见的应用是计算一个图中连通分量的个数.比如: a e / \ | b c f | | d g 上图的连通分量的个数为 2 . 并查集的主要思想是在每个连 ...

随机推荐

  1. 【一天一道LeetCode】#74. Search a 2D Matrix

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Write a ...

  2. 《java入门第一季》之Math类一个小案例获取任意数值范围内随机数

    Math:用于数学运算的类. import java.util.Scanner; /* * 需求:请设计一个方法,可以实现获取任意范围内的随机数. * * 分析: * A:键盘录入两个数据. * in ...

  3. Java 与 C++ 不一样的地方(持续更新中...)

    本文仅以记录 Java 与 C++ 不同之处,以备随时查询. Java 程序运行机制 Java 是一门编译解释型的语言,即它在运行的过程中既需要编译也需要解释.如下图表示的是 Java 程序运行机制: ...

  4. android 开源图表库MPChart最简单使用方法示例教程Demo--折线图 柱状图

    转载请注明本文出处:http://blog.csdn.net/wingichoy/article/details/50428246 MPChart是android上一款强大的图表开源库,他可以轻松的绘 ...

  5. apache tomcat集群

    今天花了大概两个小时完成了tomcat与apache的集群.现记录一下,也希望能帮助后来者. 建议看这篇博客前,先阅读一下鄙人拙作 tomcat整合apache 看完那个后,再进行集群,就很快了. 和 ...

  6. 结合FireBreath在Chrome/FireFox的多进程模式下崩溃一例

    FireBreath是跨浏览器跨操作系统的插件方案,它封装了ActiveX和NPAPI的插件接口,使用统一的API来暴露JSAPI.Chrome和FireFox使用NPAPI,IE使用ActiveX. ...

  7. windows下mysql免安装配置

    我下载的是mysql-5.5.20-win32.zip版本 1.解压 2.配置环境变量(让系统知道你的bin在哪个位置)path里面设置到安装目录的bin目录 3.复制一个my-huge.ini 另存 ...

  8. 史上最全webview详解

    本文来自:http://www.jianshu.com/users/320f9e8f7fc9/latest_articles WebView在现在的项目中使用的频率应该还是非常高的. 我个人总觉得HT ...

  9. HBase flush

    flush触发方式 1. Server端执行更新操作(put.delete.multi(MultiAction<R>multi).(private)checkAndMutate.mutat ...

  10. 织云 Metis:看腾讯怎么做智能运维

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作为企业智能运维门户,业界早已关注织云的智能运维体系.我们很荣幸地宣布织云 Metis 智能运维体系正式发布.自此,织云家族已发布:织云企业 ...