ACM数据结构-并查集
ACM数据结构-并查集
并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
主要操作
初始化
查找
合并
部分代码如下:
const int MAXSIZE = 100005; int pre[MAXSIZE]; void makeSet(int size)
{
for(int i=0;i<size;i++)
pre[i]=i;
}
接下来find操作
int find(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
return r;
} void Merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
pre[fx]=fy;
}
下面是两个版本的find操作:
int find(int x)
{
if(x!=pre[x])
pre[x]=find(pre[x]);
return pre[x];
}
递归版
int find(int x)
{
int r=x , t;
while(pre[r]!=r)
r=pre[r]; //返回根节点
while(r!=x) //路径压缩
{
t=pre[x];
pre[x]=r;
x=t;
}
return x;
}
非递归版
最后是合并操作 unionSet,并查集的合并也非常简单,就是将一个集合的树根指向另一个集合的树根,如图 所示。
这里也可以应用一个简单的启发式策略——按秩合并。该方法使用秩来表示树高度的上界,在合并时,总是将具有较小秩的树根指向具有较大秩的树根。简单的说,就是总是将比较矮的树作为子树,添加到较高的树中。为了保存秩,需要额外使用一个与 pre 同长度的数组,并将所有元素都初始化为 0。
void unionSet(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy)
return ;
if(rank[fx]>rank[fy])
pre[fy]=fx;
else
{
pre[fx]=fy;
if(rank[fx]==rank[fy])
rank[fy]++;
}
}
除了按秩合并,并查集还有一种常见的策略,就是按集合中包含的元素个数(或者说树中的节点数)合并,将包含节点较少的树根,指向包含节点较多的树根。这个策略与按秩合并的策略类似,同样可以提升并查集的运行速度,而且省去了额外的 rank 数组。
这样的并查集具有一个略微不同的定义,即若 uset 的值是正数,则表示该元素的父节点(的索引);若是负数,则表示该元素是所在集合的代表(即树根),而且值的相反数即为集合中的元素个数。相应的代码如下所示,同样包含递归和非递归的 find 操作:
const int MAXSIZE = 1000005; int pre[MAXSIZE]; void makeSet(int size)
{
for(int i = 0;i < size;i++)
pre[i] = -1;
} int find(int x)
{
if (pre[x] < 0)
return x;
pre[x] = find(pre[x]);
return pre[x];
} int find(int x)
{
int r = x, t;
while (pre[r] >= 0)
r = pre[r];
while (x != r)
{
t = pre[x];
pre[x] = r;
x = t;
}
return x;
} void unionSet(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx==fy)
return;
if (pre[fx] < pre[fy])
{
pre[fx] += pre[fy];
pre[fy] = fx;
}
else
{
pre[fy] += pre[fx];
pre[fx] = fy;
}
}
如果要获取某个元素 x 所在集合包含的元素个数,可以使用 -pre[find(x)] 得到。
ACM数据结构-并查集的更多相关文章
- 算法手记 之 数据结构(并查集详解)(POJ1703)
<ACM/ICPC算法训练教程>读书笔记-这一次补上并查集的部分.将对并查集的思想进行详细阐述,并附上本人AC掉POJ1703的Code. 在一些有N个元素的集合应用问题中,通常会将每个元 ...
- ACM: The Suspects-并查集-解题报告
The Suspects Time Limit:1000MS Memory Limit:20000KB 64bit IO Format:%lld & %llu Description 严重急性 ...
- 图论&数据结构——并查集
Wikioi 4246 NOIP模拟赛Day2T1 奶牛的身高 题目描述 Description 奶牛们在FJ的养育下茁壮成长.这天,FJ给了奶牛Bessie一个任务,去看看每个奶牛场中若干只奶牛的 ...
- POJ 1703 Find them, Catch them (数据结构-并查集)
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 31102 Accepted: ...
- acm专题--并查集
题目来源:http://hihocoder.com/problemset/problem/1066 #1066 : 无间道之并查集 时间限制:20000ms 单点时限:1000ms 内存限制:256M ...
- 《挑战程序设计竞赛》2.4 数据结构-并查集 POJ1182 2236 1703 AOJ2170
POJ1182 http://poj.org/problem?id=1182 题目 难得的中文题... 食物链 Time Limit: 1000MS Memory Limit: 10000K Tota ...
- 第三十一篇 玩转数据结构——并查集(Union Find)
1.. 并查集的应用场景 查看"网络"中节点的连接状态,这里的网络是广义上的网络 数学中的集合类的实现 2.. 并查集所支持的操作 对于一组数据,并查集主要支持两种操作:合并两 ...
- 【题解】P2024 [NOI2001]食物链 - 数据结构 - 并查集
P2024 [NOI2001]食物链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 动物王国中有三类动物 \(A,B ...
- <数据结构>并查集与树
作用 查:给定一个元素,查询它在哪个集合内 并:合并两个元素所在的集合 实现思路 对应关系 元素-->结点 集合-->树 多个集合-->森林 用树的根节点作为不同树的标志 合并时只需 ...
随机推荐
- 关于浏览器被http://www.51jetso.com/劫持
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wwkaven/article/details/36373447 近期,新装了一下系统.安装软 ...
- 记一次关于SSM框架的使用错误
今天遇到一个十分操蛋的问题,最后发现是因为忘记在对应的Service上加上@AutoWired. 难怪单元测试没问题,因为单元测试中用到的Service,其实现类通过DAO自动装配了.也就是在对应的s ...
- 树莓派图形界面启动chromium并全屏
方法1. 随便一搜都是这种方法 创建文件: /home/pi/.config/autostart/my.desktop 文件名随意, 后缀必须.desktop 文件内容: [Desktop ...
- CentOS7 安装配置备忘录
1. 安装 epel 源 $ sudo yum install epel-release.noarch 如果想强制服务器使用 tuna 的镜像,可以如下修改 /etc/yum.repos.d/epel ...
- Flex布局(一)flex-direction
采用Flex布局的元素,被称为Flex容器(flex container),简称"容器".其所有子元素自动成为容器成员,成为Flex项目(Flex item),简称"项目 ...
- 课时46.label标签(掌握)
我们点击QQ注册页面,发现了一个问题,当我们点击密码两个字的时候,输入框聚焦了,而点击确认密码的时候,输入框也聚焦了,而我们上节课做的页面,这么点击,并不聚焦 1.默认情况下文字和输入框是没有关联关系 ...
- 管理Django1.9静态文件static
管理Django1.9静态文件static 网站通常需要增加图片.JavaScript.或者CSS等文件提供服务.在Django中,我们把这些文件称为“静态文件”(static files).Djan ...
- iOS:UICollectionView流式布局及其在该布局上的扩展的线式布局
UICollectionViewFlowLayout是苹果公司做好的一种单元格布局方式,它约束item的排列规则是:从左到右依次排列,如果右边不够放下,就换一行重复上面的方式排放,,,,, 常用的 ...
- Head First Java学习笔记
1.基本概念 1.1.工作方式 源代码(.java)---编译器(执行javac程序)---产生字节码(.class与平台无关)---JAVA虚拟机(JVM,读取与执行字节码) 1.2.汇编语言是对基 ...
- jQuery 遍历 - children() 方法 获取指定id下子元素的值
<a id="Aobj_2_2" class="" specid="2" specvid="2" href=&qu ...