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) ...
随机推荐
- 【BUAA 软工个人项目作业】玩转平面几何
BUAA 软件工程个人项目作业 项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:BUAA软件工程个人项目作业 作业要求 课程目标 学习大规模软件开发的技巧与方法 ...
- import 更新变量
其他的模块的变量一经引用,是定值,只能再次import才能更新他的值
- 重新整理 .net core 实践篇————配置应用[一]
前言 本来想整理到<<重新整理.net core 计1400篇>>里面去,但是后来一想,整理 .net core 实践篇 是偏于实践,故而分开. 因为是重新整理,那么就从配置开 ...
- [bug] Flask:jinja2.exceptions.UndefinedError: 'None' has no attribute 'id'
问题 Python Flask做的购物网站,添加购物车时,提示错误 解决 检查发现是MySQL中不正常的空数据导致,删除此条记录即可 参考 https://www.jb51.cc/python/186 ...
- 安装 Centos 7.x
学习 python 至今,一直是在 linux 上操作,感觉还是 linux 对 python 的支持更加友好,默认安装了 python 的版本 2 和 3 .为了打造更好的 python 开发环境, ...
- Windows10 添加 新的输入法
Windows10系统 控制面板 区域 语言首选项 设置 添加 陈桥输入法
- Ansible_常用模块
一.Ansible常用模块 1.ansible常用模块command.shell.raw的区别: command模块不是调用的shell的指令,所以没有bash的环境变量 shell模块调用的/bin ...
- Linux进阶之日志管理
一.何为日志 1.在程序执行时,可以通过标准输出以及错误输出,让我们知道程序的执行情况,而系统不可能将所有程序的输出信息一起显示,要知道后台执行的程序非常之多,如果一起显示,那我们不用操作了,整天只看 ...
- Python数模笔记-StatsModels 统计回归(4)可视化
1.如何认识可视化? 图形总是比数据更加醒目.直观.解决统计回归问题,无论在分析问题的过程中,还是在结果的呈现和发表时,都需要可视化工具的帮助和支持. 需要指出的是,虽然不同绘图工具包的功能.效果会有 ...
- 第14讲 | HTTP协议:看个新闻原来这么麻烦
第14讲 | HTTP协议:看个新闻原来这么麻烦 http://www.163.com 是个 URL,叫作统一资源定位符. 之所以叫统一,是因为它是有格式的.HTTP 称为协议,www.163.com ...