hdu1232 并查集总结
前言
在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
这一类问题其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。
定义
并查集(Disjoint Set),即“不相交集合”,是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。
将编号分别为1…N的N个对象划分为不相交集合,在每个集合中,选择其中某个元素代表所在集合。
常见两种操作:
- 合并两个集合
- 查找某元素属于哪个集合
用编号最小的元素标记所在集合;定义一个数组set[1...n],其中set[i]表示元素i 所在的集合;

算法实现
查找
时间复杂度:\(O(1)\)
find1(x)
{
return set[x];
}
合并
时间复杂度:\(O(n)\)
Merge1(a,b)
{
i = min(a,b);
j = max(a,b);
for (k = 1; k <= N; k++) {
if (set[k] == j)
set[k] = i;
}
}
对于合并操作,必须搜索全部元素!有没有可以改进的地方呢?
算法的优化
使用树结构
每个集合用一棵“有根树”表示,定义数组set[1...n]
set[i] = i,则 i 表示本集合,并且是集合所对应树的根set[i] = j,j<>i,则 j 是 i 的父节点

查找
时间复杂度(最坏):\(O(n)\)
find2(x)
{
r = x;
while (set[r] != r)
r = set[r];
return r;
}
合并
时间复杂度:\(O(1)\)
merge2(a, b)
{
if (a<b)
set[b] = a;
else
set[a] = b;
}
避免最坏情况
方法:将深度小的树合并到深度大的树
实现:假设两棵树的深度分别为h1和h2, 合并后的树的高度为h,则
\begin{cases}
max(h1, h2), & \text{if h1<>h2} \\
h1+1, & \text{if h1=h2}
\end{cases}
\]
效果:任意顺序的合并操作以后,包含k个节点的树的最大高度不超过\(\log_2{k}\)
查找
时间复杂度:\(O(\log_2{n})\)
find2(x)
{
r = x;
while (set[r] != r)
r = set[r];
return r;
}
合并
时间复杂度:\(O(1)\)
merge3(a,b)
{
if (height(a) == height(b)) {
height(a) = height(a) + 1;
set[b] = a;
} else if (height(a) < height(b)) {
set[a] = b;
} else {
set[b] = a;
}
}
路径压缩
思想:每次查找的时候,如果路径较长,则修改信息,以便下次查找的时候速度更快。
步骤:
- 找到根结点
- 修改查找路径上的所有节点,将它们都指向根结点
路径压缩示意图:

查找
find3(x)
{
r = x;
while (set[r] != r) //循环结束,则找到根节点
r = set[r];
i = x;
while (i != r) //本循环修改查找路径中所有节点
{
j = set[i];
set[i] = r;
i = j;
}
}
hdu1232
#include<stdio.h>
int x[1005];
int min(int a,int b);
int max(int a,int b);
void xs(int a,int b);
int fine(int a);
int main()
{
int n,m,i,a,b;
while(scanf("%d",&n)&&n)
{
int sum = -1;
scanf("%d",&m);
for(i=1;i<=n;i++) x[i]=i; //首先把各自的父节点设为自身
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
xs(a,b); //合并两个集合
}
for(i=1;i<=n;i++)
{
if(x[i]==i) sum++; //算出(最后不同集合的个数-1)即为所求
}
printf("%d\n",sum);
}
return 0;
}
int min(int a,int b)
{
return a<b ? a : b;
}
int max(int a,int b)
{
return a>b ? a : b;
}
int fine(int a)
{
if(x[a]==a) return a;
else return fine(x[a]);
}
void xs(int a,int b)
{
x[max(fine(a),fine(b))] = min(fine(a),fine(b));
}
hdu1232 并查集总结的更多相关文章
- hdu1232 并查集
1. hdu1232 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232 3.总结:简单并查集 #include<iostream> # ...
- 畅通工程--hdu1232(并查集)
畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 并查集入门(hdu1232“畅通工程”)
在学习并查集之前,首先需要明白基本的并查集可以完成的功能.并查集主要是用于处理不相交集合的合并问题.它是一种基础算法,在离散数学中,可以利用并查集求一个图的连通分支,利用其这个特性可以为我们解决一系列 ...
- hdu1232 城镇间修路(并查集)
问题是这样的: Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇 ...
- HDU1232 畅通工程 并查集
畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 【HDU1232】畅通工程(并查集基础题)
裸敲并查集,很水一次AC #include <iostream> #include <cstring> #include <cstdlib> #include &l ...
- [HDU1232] 畅通工程 (并查集 or 连通分量)
Input 测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的 ...
- 利用并查集+贪心解决 Hdu1232
畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU1232——畅通工程【并查集】
<题目链接> 题目大意: 利用并查集找出图中有几个不连通的城镇集合,所需修的道路数即为城镇集合-1. #include <stdio.h> ]; int find(int x) ...
随机推荐
- Sentinel导航
简介 最近都在弄微服务的东西,现在来记录下收获.我从一知半解到现在能从0搭建使用最大的感触有两点 1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功 2.网上 ...
- Mac 将 App 程序打包成为 dmg
用最简单的打包方式,将自己开发的App打包成为DMG,实现共享分发,快速安装 1. 新建DMG 打开磁盘工具,新建DMG File->New Image->Blank Image 创建DM ...
- 使用sosreport命令生成诊断包
[RHEL]-7-常用系统状态检测命令 引言 这篇文章介绍RHEL中最常用的几个系统状态检测命令,包括:网络状态.内存.主机名及其架构.系统负载及其用户登录状态等. 文章目录 0×1.查看网络状态 0 ...
- Vim安装记录
Vim安装记录 参考链接 安装命令 1. 安装依赖库 2. 下载最新vim源码 3. 删除旧版vim 4. 配置configure.编译.安装 5. 设置vim为默认编辑器 6. 必要的配置 Vim安 ...
- C++ Error 个人笔记(live)
1.error: invalid conversion from 'char' to 'char*' [-fpermissive] 原因: 把一个字符型的变量赋值给了一个字符型的指针 我的原因: 把 ...
- Flex里的fx s mx
笔记是从其他地方整合的,仅供参考 原来flex build 4有三个命名空间fx,mx,s,分别对应一下三个: •xmlns:fx="http://ns.adobe.com/mxml/200 ...
- Python使用 Kubernetes API 访问集群
通过将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理,像这样:使用 grep/cut 方式: 通过将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理, ...
- GO学习-(37) 使用Air实现Go程序实时热重载
使用Air实现Go程序实时热重载 今天我们要介绍一个神器--Air能够实时监听项目的代码文件,在代码发生变更之后自动重新编译并执行,大大提高gin框架项目的开发效率. 为什么需要实时加载? 之前使用P ...
- python 获取时间范围内日期列表
python 获取时间范围内日期列表 import datetime def dateRange(beginDate, endDate): dates = [] dt = datetime.datet ...
- NVIDIA安培架构
NVIDIA安培架构 NVIDIA Ampere Architecture In-Depth 在2020年英伟达GTC主题演讲中,英伟达创始人兼首席执行官黄仁勋介绍了基于新英伟达安培GPU架构的新英伟 ...