hdu1232(并查集)
2016-02-02 19:15
375 查看
关于并查集,最主要的是是这样的一张图
也就是维护与查询集合。
而为了加快查询查询,可以进行的就是将上图的左集合变换为右集合,称之为压缩路径。
因为我们只想知道该元素是否属于某集合,所以路径压缩虽然改变了元素的前驱,但是保留的是父节点,也就是顶点。
我们考虑单链的情况,如果存在单链如图
那么通过优化,可得
如果元素多了之后,查询两元素是否属于同一集合,则可以将O(n)的复杂度降为O(1),这样对于多次查询的情况,可以极大提高效率。
以HDU1232为例,代码如下
其中
Find函数为查询元素x,并返回父元素r。代码里的是已经进行了路径压缩后的查询函数。
Join函数为合并元素,将x与y合并,置入一个集合。
集合的初始化我写到了main函数里,是这两句代码
也就是维护与查询集合。
而为了加快查询查询,可以进行的就是将上图的左集合变换为右集合,称之为压缩路径。
因为我们只想知道该元素是否属于某集合,所以路径压缩虽然改变了元素的前驱,但是保留的是父节点,也就是顶点。
我们考虑单链的情况,如果存在单链如图
那么通过优化,可得
如果元素多了之后,查询两元素是否属于同一集合,则可以将O(n)的复杂度降为O(1),这样对于多次查询的情况,可以极大提高效率。
以HDU1232为例,代码如下
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int pre[1050]; int Find(int x) //已优化 { int r = x; while(pre[r] != r) r = pre[r]; int i = x, j; while (i != r) { j = pre[i]; pre[i] = r; i = j; } return r; } void Join(int x, int y) { int fx = Find(x), fy = Find(y); if (fx != fy) pre[fx] = fy; } int main() { int n, m; while (scanf("%d%d", &n, &m) && n) { for (int i = 1; i <= n; i++) pre[i] = i; for (int i = 0; i < m; i++) { int s, e; scanf("%d%d", &s, &e); Join(s, e); } int ans = 0; for (int i = 1; i <= n; i++) if (pre[i] == i) ans++; printf("%d\n", ans - 1); } return 0; }
其中
Find函数为查询元素x,并返回父元素r。代码里的是已经进行了路径压缩后的查询函数。
Join函数为合并元素,将x与y合并,置入一个集合。
集合的初始化我写到了main函数里,是这两句代码
for (int i = 1; i <= n; i++) pre[i] = i;可以单独提出来写成一个初始化函数。
相关文章推荐
- React项目搭建基于Karma的CI环境
- 【自语】如何前后端的web及移动都打通?
- map.entry 的作用
- C++引用计数(reference counting)技术简介(3)
- C++引用计数(reference counting)技术简介(3)
- Facebook的Web开发三板斧:React.js、Relay和GraphQL
- 欢迎使用CSDN-markdown编辑器
- linux防火墙的相关操作
- 杭电题库刷题记录2015
- 怎样删除数据库中的反复记录?
- HTTPClient模块的HttpGet和HttpPost
- android studio导入第三方库引发的问题和解决方法
- STL 源代码剖析 算法 stl_algo.h -- partition
- SILK : SILK_RTP_PayloadFormat 中文翻译
- HDU 5616 Jam's balance
- JMS基础(2)
- JMS消息传输机制
- ElasticSearch immense term错误
- Java基础:关键字(保留字)
- 人见人爱A^B