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) ...
随机推荐
- 前端面试 CSS三大特性
CSS的三大特性 1.层叠性 代码由上向下执行,相同选择器设置到同一元素上,样式冲突的,会执行比较靠近html的样式,样式不冲突的情况下不影响 代码如下 <!DOCTYPE html> & ...
- 基础知识:DFRduino UNO R3最全资料详解
一.概述篇:1. 什么是DFRduino UNO R3?DFRduino UNO R3是一块基与开放原始代码的Simple i/o平台,並且具有使用类似java,C语言的开发环境.让您可以快速使用Ar ...
- [刷题] 283 Move Zeros
要求 将所有的0,移动到vector的后面比如; [1,3,0,12,5] -> [1,3,12,5,0] 实现 第一版程序,时间.空间复杂度都是O(n) 1 #include<iostr ...
- CPU缓存是位于CPU与内存之间的临时数据交换器,它的容量比内存小的多但是交换速度却比内存要快得多。CPU缓存一般直接跟CPU芯片集成或位于主板总线互连的独立芯片上
一.什么是CPU缓存 1. CPU缓存的来历 众所周知,CPU是计算机的大脑,它负责执行程序的指令,而内存负责存数据, 包括程序自身的数据.在很多年前,CPU的频率与内存总线的频率在同一层面上.内存的 ...
- 运维常用shell脚本二(压缩文件、过滤不需要的文件、检测进程)
一.压缩指定目录下的文件并删除原文件 #!/bin/bashZIP_DAY=7 function zip { local dir=$1 if [ -d $dir ];then local file_n ...
- 065.Python框架Django-DRF
一 WEB应用模式 在开发Web应用中,有两种应用模式: 1.1 前后端不分离 1.2 前后端分离 二 API接口 为了在团队内部形成共识.防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很 ...
- systemd 进程管理详解
systemd进程管理 systemd管理的优势 1.最新系统都采用systemd管理(RedHat7,CentOS7,Ubuntu15...) 2.CentOS7 支持开机并行启动服务,显著提高开机 ...
- Java 中 volatile 关键字及其作用
引言 作为 Java 初学者,几乎从未使用过 volatile 关键字.但是,在面试过程中,volatile 关键字以及其作用还是经常被面试官问及.这里给各位童靴讲解一下 volatile 关键字的作 ...
- 解决使用go get 下载模块下载超时的问题
解决使用go get 下载模块下载超时的问题 解决使用go get 下载模块下载超时的问题 使用go env可以看到,默认的GOPROXY的值是https://proxy.golang.org, ...
- YOLOv4 资源环境配置和测试样例效果
YOLOv4 资源环境配置和测试样例效果 基本环境:cuda=10.0,cudnn>=7.0, opencv>=2.4 一.下载yolov4 git clone https://githu ...