并查集(union-find set)与Kruskal算法
并查集
并查集处理的是集合之间的关系,即‘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算法的更多相关文章
- 并查集(Union/Find)模板及详解
概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...
- POJ 1611 The Suspects 并查集 Union Find
本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每 ...
- Java 并查集Union Find
对于一组数据,主要支持两种动作: union isConnected public interface UF { int getSize(); boolean isConnected(int p,in ...
- 最小生成树(Minimum Spanning Tree)——Prim算法与Kruskal算法+并查集
最小生成树——Minimum Spanning Tree,是图论中比较重要的模型,通常用于解决实际生活中的路径代价最小一类的问题.我们首先用通俗的语言解释它的定义: 对于有n个节点的有权无向连通图,寻 ...
- POJ1182食物链(并查集经典好题)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66964#problem/E 题目思路:主要有两种思路:1.带权并查集2.挑战程 ...
- bzoj1854 [Scoi2010]游戏【构图 并查集】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1854 没想到怎么做真是不应该,看到每个武器都有两个属性,应该要想到连边构图的!太不应该了! ...
- NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并
思路: Kruskal求最大生成树+倍增LCA // by SiriusRen #include <cstdio> #include <cstring> #include &l ...
- 图-连通分量-DFS-并查集-695. 岛屿的最大面积
2020-03-15 16:41:45 问题描述: 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二 ...
- 并查集 & 最小生成树详细讲解
并查集 & 最小生成树 并查集 Disjoint Sets 什么是并查集? 并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将 ...
- [leetcode] 并查集(Ⅰ)
预备知识 并查集 (Union Set) 一种常见的应用是计算一个图中连通分量的个数.比如: a e / \ | b c f | | d g 上图的连通分量的个数为 2 . 并查集的主要思想是在每个连 ...
随机推荐
- Java实现简易的文本编辑器
需求分析: 获得文本名称 实现尾部追加功能 实现覆盖式添加数据 删除数据 获取光标位置 在特定光标位置处添加数据 查找特定字符串在主串中第一次出现的位置 统计文本文件内出现的数字,汉字,英文字母,特殊 ...
- 常用Map实现类对比
翻译人员: 铁锚 翻译时间: 2013年12月12日 原文链接: HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap Map 是最常用的数据结构之一 ...
- 【嵌入式开发】C语言 结构体相关 的 函数 指针 数组
. 作者 : 万境绝尘 转载请注明出处 : http://www.hanshuliang.com/?post=30 . 结构体概述 : 结构体是 多个 变量的集合, 变量的类型可以不同; -- 可进行 ...
- InfoQ访谈:Webkit和HTML5的现状和趋势
原网址: http://www.infoq.com/cn/interviews/status-and-trends-of-webkit-and-html5 个人一些不成熟的见解,望讨论和指正. 节选 ...
- AngularJS进阶(二十七)实现二维码信息的集成思路
AngularJS实现二维码信息的集成思路 赠人玫瑰,手留余香.若您感觉此篇博文对您有用,请花费2秒时间点个赞,您的鼓励是我不断前进的动力,与君共勉! 注:点击此处进行知识充电 ...
- Oracle Applications DBA 基础(二)
6.OAM及系统管理 2014年9月13日 20:40 参考资料: 1.Oracle Applications System Administrator's Guide - Configuration ...
- 关于Service中bindService注意的几个问题
最近有用到Activity需要不断的从Service中获取数据,第一个想法肯定就是通过bind回调机制了,有几点概念模糊特此记录下: 单独使用bindService(),unbindService() ...
- UnityEditor下文件操作方法汇总(Unity3D开发之二十四)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/50595585 ...
- 真机测试遇到0xE8008016错误修改方法
错误描述 真机测试过程中,更换Provisioning Profile之后,出现错误:The entitlements specified in your application's Code Sig ...
- iOS监听模式系列之对APNs的认知与理解
前言: APNs 协议在近两年的 WWDC 上改过两次, 15 年 12 月 17 日更是推出了革命性的新特性.但在国内传播的博客.面试题里关于 APNs 的答案全都是旧的.错的. 导航: 对 APN ...