并查集

并查集处理的是集合之间的关系,即‘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. 详解ebs接口之客户配置文件导入(一)

    DECLARE l_rec_profile_t hz_customer_profile_v2pub.customer_profile_rec_type; l_rec_profile hz_custom ...

  2. ORACLE sid,pid,spid总结

    概念上:1.spid (system process id)  是操作系统层面的进程id .2.pid(process id)  这个是基于oracle的进程id个人理解为就是oracle给自己的进程 ...

  3. 二叉树的最大深度算法面试题-leetcode学习之旅(3)

    标题 Maximum Depth of Binary Tree 描述 The maximum depth is the number of nodes along the longest path f ...

  4. 内存数据网格hazelcast的一些机制原理

    hazelcast作为一个内存数据网格工具,还算比较优秀,听说有Apache顶级项目使用它,值得研究下,使用文档可以直接看官方文档,但机制原理相关的资料基本没有,本人硬撸源码写的一些东西,跟大家分享一 ...

  5. 用curl采集需要登录的页面

    登陆cookie存储至自定义目录 $cookie_dir = tempnam('.', 'cookie');curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_ ...

  6. java工具类(五)之日期格式字符串与日期实现互转

    JAVA字符串转日期或日期转字符串 项目开发过程中需要实现日期格式的字符串与日期进行互转,并进行日期的加减操作. Demo如下: package weiming.lmapp.utils; import ...

  7. OpenCV 透视变换实例

    参考文献: http://www.cnblogs.com/self-control/archive/2013/01/18/2867022.html http://opencv-code.com/tut ...

  8. ATPCS

    ATPCS是: Arm Thumb procedure Call Standard的缩写.意思是arm thumb子程序调用规范.      C语言函数与C函数之间进行调用是用同一个C函数调用方式进行 ...

  9. 给大家推荐一个python的学习网站 http://www.codecademy.com

    注册之后,可以跟着指导,自己编码学习,比较方面: 再推荐一个在线编译的代码网站,c/c++ python  都可以: http://codepad.org

  10. 从开发者角度解析 Android N 新特性!

    大清早看到 Google 官方博客发布 Android N 的开发者预览版,立马从床上跳起来开始仔仔细细的读起来. 从开发者角度来看,Android N 的更新并不算大.网上之前流传的一些 Andro ...