《ACM/ICPC算法训练教程》读书笔记-这一次补上并查集的部分。将对并查集的思想进行详细阐述,并附上本人AC掉POJ1703的Code。


  在一些有N个元素的集合应用问题中,通常会将每个元素构成单元素集合,然后按照一定顺序将同属一组的集合合并,期间要反复查找每一个元素在哪个集合中。这类问题往往看似简单,但是数据量很大,因此容易造成TLE或MLE,也就是空间度和时间度极其复杂。因此在这里,我们引入一种抽象的特殊数据结构——并查集。

  并查集:类似一个族谱,每个结点均有一个father[x]来表示x结点的父结点,因此,我们在给并查集初始化的时候,先将结点设为自己的父结点,也就是: father[x] = x; ,依次初始所有结点。

  并查集有两种重要的操作:查找合并

查找

  并查集为避免时间上和空间上的损耗,在每一轮查找时,都要进行一次路径压缩优化。什么叫做路径压缩呢,简单的说就是将所有子结点都直接归属其根结点,减小代差,这样父辈和子辈就方便"交流"了。

  具体来说,在查找时,如果得到3的父结点为1,而1的父结点为2,2的父结点又为4,就依次完成: father[3] = father[1] = father[2] = 4;

  这样的优势就在于待到下一次查找时,可以直接进行一次操作完成查询,而不需多次操作“寻根问底”。

  在这里我们利用递归的思想让这段代码实现起来简便易行:

 1 /*查找并压缩路径*/
 2 int Find_set(int x)
 3 {
 4     int temp = fa[x];
 5     if(x != fa[x])
 6         fa[x] = Find_set(fa[x]);    //路径压缩
 7     return fa[x];
 8 }
 9 /*使用*/
10 p[x] = Find_set(x);

合并

  也就是合并x和y所在的两个集合,简单来说,只需要把其中一个集合的根节点赋给另一个集合的根节点就可以了。因此此时需要进行一次查询操作并查找到x和y所在集合的两个根节点。

  具体实现如下:

1 void Union(int x,int y)
2 {
3     int fx = Find_set(x);
4     int fy = Find_set(y);
5     if (fx == fy)    //根节点Same
6         return;
7     father[fx] = fy;
8 }

  本书在这里给出的Code包括了启发式合并:也就是将深度小的根节点挂在深度大的根节点上,这样每次查询时进行路径压缩的次数就会得到优化。

  但是我认为初学的时候摊上这个就有点麻烦了,而且这种优化在一定程度来说写起来比较繁琐,因此就没有在这里贴出来了,在某些极端情况下可以加上启发式合并试试。

  那么像这样利用路径压缩就可以将并查集的时间复杂度看做O(1),空间复杂度为O(n),这样就将一个大规模问题转化为一个空间小,速度极快的简单操作。


  POJ1703解题报告:

  题目大意:Tadu City中有两个黑帮团伙,一共n名团伙成员(不知道属于哪个组织),现在警察局有一些信息,每条信息包括两个人的编号:

  输入D x y:代表x于y不在一个团伙里
  输入A x y:询问x与y是否在同一团伙或者不确定他们在同一个团伙里

  

  那么在这种题目中,我们用并查集的思想可以避免大规模地遍历每个成员。那么具体来说如何实现呢。

  如果定义两个帮派集合,那么在大量的D x y中也可能无法确认谁属于哪个帮派,而如果定义每个人一个帮派,那么就可以将并查集的思想利用起来,为了表明成员间的关系,因此我们在这里加入一个relate[x]来表明x结点与其父结点的关系。我们用1来表示这两个成员是不同帮派,而用0来表示这两个成员属于同一个帮派。

  大家可以先打个草稿来尝试如何将大量D x y数据合并(注意relate[]的调整)

  Code仅供参考:

  

 1 //并查集:D x y 表示x和y分属不同帮派,A x y表示查询x和y的关系
 2 //在并查集的基础上加上relate[],表示t与其父结点fa[t]的关系
 3 //Memory:948K Time:344Ms
 4 #include<iostream>
 5 #include<cstring>
 6 #include<cstdio>
 7 using namespace std;
 8 #define MAX 100005
 9 int n, m;
10 int fa[MAX], r[MAX];    //father node - relation
11 int find(int x)
12 {
13     if (x != fa[x]) {
14         int pa = fa[x];
15         fa[x] = find(fa[x]);    //路径压缩
16         r[x] ^= r[pa];    //改变关系
17     }
18     return fa[x];
19 }
20 int main()
21 {
22     int T;
23     scanf("%d", &T);
24     while (T--)
25     {
26         scanf("%d%d", &n, &m);
27         memset(r, 0, sizeof(r));
28         for (int i = 0; i <= n;i++)
29             fa[i] = i;
30         while (m--)
31         {
32             int c1, c2;
33             char flag;
34             scanf("\n%c%d%d", &flag, &c1, &c2);
35             //找出根节点
36             int p1 = find(c1), p2 = find(c2);
37             if (flag == 'A')
38             {
39                 if (p1 != p2)
40                     printf("Not sure yet.\n");
41                 else if (r[c1] == r[c2])
42                     printf("In the same gang.\n");
43                 else printf("In different gangs.\n");
44             }
45             else {
46                 fa[p1] = p2;
47                 r[p1] = r[c1] == r[c2];    //c1-p1与c2-p2关系相同则p1与p2关系不同,反之亦然
48             }
49         }
50     }
51     return 0;
52 }

转载于:https://www.cnblogs.com/Inkblots/p/4935456.html

算法手记 之 数据结构(并查集详解)(POJ1703)相关推荐

  1. 并查集详解 ——图文解说,简单易懂(转)特别好玩

    并查集详解 --图文解说,简单易懂(转) 2016年03月10日 17:38:08 阅读数:6931 标签: 并查集数据结构并查集算法图文解说 更多 个人分类: 算法--并查集 并查集是我暑假从高手那 ...

  2. 拓扑排序 详解 + 并查集 详解 + 最小生成树详解

    若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   : http://www.cnblogs.com/Yan-C/p/3943940.htm ...

  3. 数据结构(八):并查集详解 (多图+动图)

    目录 一.什么是并查集 二.并查集的存储结构 三.并查集的基本操作 (一)初始化 (二)Find操作 (三)Union操作 四.并查集的优化 (一)Union操作优化(小树并入大树) (二)Find操 ...

  4. [数据结构、读书笔记、C++] 并查集详解

    介绍 并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的 合并及查询 问题. 其主要操作为: Union(合并) :将两个节点所在集合合并为一个集合 Find (查询) ...

  5. 【数据结构之并查集】并查集详解(零基础入门,超级有趣的!!!)

    转的一个超级有意思,好懂的并查集解释, 膜拜大神~~ 故事读完,并查集就会了~~~~~ 江湖上散落着各式各样的大侠,有上千个之多.他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的 ...

  6. 7-3 最小生成树-kruskal (10 分)(思路+详解+并查集详解+段错误超时解决)宝 Come

    一:前言 本题需要用到并查集的知识,建议先学完并查集后再看看本题 二:题目 题目给出一个无向连通图,要求求出其最小生成树的权值. 温馨提示:本题请使用kruskal最小生成树算法. 输入格式: 第一行 ...

  7. - 并查集详解(第二节)

    以下是并查集思路详解: 一:概念 并查集处理的是"集合"之间的关系.当给出两个元素的一个无序数对(a,b)时,需要快速"合并"a和b分别所在的集合,这期间需要反 ...

  8. 并查集详解:UF——UF_Tree——UF_Tree_Weighted逐步优化

    目录 1 并查集简介 2 UF 2.1 UF(int N)构造方法实现 2.2 union(int p, int q)合并方法实现 2.3 代码实现(Java) 2.4 应用举例与复杂性分析 3 UF ...

  9. 并查集详解(从引入到代码)

    江湖上散落着各式各样的大侠,有上千个之多.他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架.但大侠们有一个优点就是讲义气,绝对不打自己的朋友.而且他们信奉&qu ...

  10. 一个很有意思的并查集详解

    并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了.以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定.不分享出来真是对不起party了.(party:我靠,关我嘛事啊?我跟你很熟么?) ...

最新文章

  1. JSFL元件类型判断 转载于 https://blog.csdn.net/linking530/article/details/8364600
  2. 分享Kali Linux 2017年第12周镜像文件
  3. python程序设计——函数设计与调用
  4. Exception: This is not supported, use MenuItemCompat.getActionProvider()的处理
  5. oracle status
  6. mysql的索引的作用_数据库索引的作用,优点和缺点
  7. 计算机总是无法响应怎么办,电脑无响应是怎么回事 电脑无响应解决方法
  8. 字符编码、常见字符集解析(ASCII、Unicode、UTF-8、GB2312等)
  9. Android Studio 导入 so 简明教程:通过一个示例让你理解整个过程
  10. 微信 android 省略号,安卓版微信再现重大Bug,点击链接直接崩溃
  11. c语言全面,最新版c语言经典习题100例(最全面).doc
  12. Node.js 开发者的 Rust 入门指南
  13. DevOps冲击下的软件测试
  14. windows10查看本机IP脚本
  15. (图)关键路径算法 (含AOV AOE网比较)
  16. Win系统 - 微星 GS65 笔记本电脑开机黑屏
  17. 第六周作业1——利用哈夫曼编码英文字母表
  18. 计算机网络WAN接口,无线路由器WAN口连接类型如何选择【详细介绍】
  19. 由一个日期, 怎样知道是星期几?
  20. GUPNet:基于几何不确定性映射的单目3D检测网络(ICCV2021)

热门文章

  1. 利用opencv生成面膜
  2. pandas获取符合条件值的索引
  3. pytorch view()函数
  4. yolov5模型框架详解
  5. 【RBM】受限玻尔兹曼机(Restricted Boltzmann Machine, RBM) 简介
  6. python实现递归和非递归求两个数最大公约数、最小公倍数
  7. matlab solve 矩阵方程,用solve函数能求解带有未知数的矩阵方程组吗
  8. python中showinfo什么意思_在Python中Windows – 在startupinfo中使用wShowWindow的Popen不会影响显示...
  9. 区块链学习路线图 初阶+中阶+高阶
  10. 【Django 2021年最新版教程36】 python django runserver 后台运行