并查集

比眉伴天荒 2021-06-22 15:37 642阅读 0赞
  1. 并查集的作用就是快速判断两个元素是否在同一个集合中,快速将两个集合合并
  2. 基本模板
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. const int maxn=1e5+10;
  7. int n,m;
  8. int f[maxn];// 当前节点的父节点
  9. int find(int x){ //路径压缩的写法 ,返回的该节点的祖宗节点
  10. if(x!=f[x]){ //如果一个点的父亲节点是本身就说明
  11. f[x]=find(f[x]);
  12. }
  13. //查找x所在集合的祖先节点下标,将x的父亲节点指向祖先节点
  14. return f[x];
  15. }
  16. int main(){
  17. cin>>n>>m;
  18. for(int i=1;i<=n;i++){
  19. f[i]=i;//首先将每个节点的父亲初始化为自己本身,自己是一个集合
  20. }
  21. char c;
  22. while(m--){
  23. cin>>c;
  24. int a,b;
  25. if(c=='M'){
  26. cin>>a>>b;
  27. int fa=find(a);
  28. int fb=find(b);
  29. if(fa!=fb){ //如果a和b不是同一个集合
  30. f[fa]=fb;//将a的祖先节点的父亲指向b的祖先节点
  31. }
  32. }
  33. else if(c=='Q'){
  34. cin>>a>>b;
  35. int fa=find(a);
  36. int fb=find(b);
  37. if(fa==fb){ //如果祖先节点相同说明在一个集合中
  38. cout<<"Yes"<<endl;
  39. }
  40. else{
  41. cout<<"No"<<endl;
  42. }
  43. }
  44. }
  45. return 0;
  46. }
  47. 应用求每个集合的数量,只需要维护的是祖先节点的数量代表整个集合的数量即可
  48. 给定一个包含n个点(编号为1~n)的无向图,初始时图中没有边。
  49. 现在要进行m个操作,操作共有三种:
  50. C a b”,在点a和点b之间连一条边,ab可能相等;
  51. Q1 a b”,询问点a和点b是否在同一个连通块中,ab可能相等;
  52. Q2 a”,询问点a所在连通块中点的数量;
  53. 输入格式
  54. 第一行输入整数nm
  55. 接下来m行,每行包含一个操作指令,指令为“C a b”,“Q1 a b”或“Q2 a”中的一种。
  56. 输出格式
  57. 对于每个询问指令”Q1 a b”,如果ab在同一个连通块中,则输出“Yes”,否则输出“No”。
  58. 对于每个询问指令“Q2 a”,输出一个整数表示点a所在连通块中点的数量
  59. 每个结果占一行。
  60. 数据范围
  61. 1n,m105
  62. 输入样例:
  63. 5 5
  64. C 1 2
  65. Q1 1 2
  66. Q2 1
  67. C 2 5
  68. Q2 5
  69. 输出样例:
  70. Yes
  71. 2
  72. 3
  73. #include <iostream>
  74. #include <algorithm>
  75. #include <string>
  76. using namespace std;
  77. const int maxn=1e5+10;
  78. int n,m;
  79. int f[maxn];// 当前节点的父节点
  80. int cnt[maxn];//统计集合内元素的数量
  81. int find(int x){ //路径压缩的写法
  82. if(x!=f[x]){ //如果一个点的父亲节点是本身就说明
  83. f[x]=find(f[x]);
  84. }
  85. //查找x所在集合的祖先节点下标,将x的父亲节点指向祖先节点
  86. return f[x];
  87. }
  88. int main(){
  89. cin>>n>>m;
  90. for(int i=1;i<=n;i++){
  91. f[i]=i;
  92. cnt[i]=1;//首先将每个节点的父亲初始化为自己本身,自己是一个集合
  93. }
  94. string op;
  95. while(m--){
  96. cin>>op;
  97. int a,b;
  98. if(op=="C"){
  99. cin>>a>>b;
  100. int fa=find(a);
  101. int fb=find(b);
  102. if(fa!=fb){ //如果a和b不是同一个集合
  103. cnt[fb]+=cnt[fa];
  104. f[fa]=fb;//将a的祖先节点的父亲指向b的祖先节点
  105. }
  106. }
  107. else if(op=="Q1"){
  108. cin>>a>>b;
  109. int fa=find(a);
  110. int fb=find(b);
  111. if(fa==fb){ //如果祖先节点相同说明在一个集合中
  112. cout<<"Yes"<<endl;
  113. }
  114. else{
  115. cout<<"No"<<endl;
  116. }
  117. }
  118. else if(op=="Q2"){
  119. int a;
  120. cin>>a;
  121. cout<<cnt[find(a)]<<endl;
  122. }
  123. }
  124. return 0;
  125. }

发表评论

表情:
评论列表 (有 0 条评论,642人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    并查集JAVA版框架 并查集是一种用来管理元素分组情况的数据结构。 并查集可以高效地进行如下操作: \--查询元素a和元素b是否属于同一组

    相关

    这个文章是几年前水acm的时候转的, 当时也不知道作者是谁, 要是有人知道的话说一下吧 并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的

    相关

    > 题目 > 某学校近期要组织全校同学出去参加某项活动,由于人数众多,学校决定让同学们自行组队,以小组为单位进行活动。假设学校一共n个同学,每个同学有一个唯一的数字作为标签

    相关

    森林: 森林是由若干棵互不相交的树组成,两棵树分别独立,没有交集 ![20181112082744488.png][] 并查集: 并查集的结构和森林十分相似,是

    相关

    来看一个实例,[杭电1232畅通工程][1232] 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性

    相关

    > 并查集是一种树形的数据结构,用于集合的合并。 与C++STL相比的优势: 1. 可以同时维护多个集合 2. 快速的合并两个集合 \\现实: 用数组实现。fat

    相关

    例题: ![输入样例][20190805122001677.png] 输入样例,第一行为一个整数n,代表有n台电脑,编号1-n;接下来进行一系列操作,当输入‘c’时,判

    相关

    一、算法解释 用于解决一些有N个元素的集合应用问题。 1、将每个元素初始化为自身单独成为一个集合。用p\[i\]的值表示该元素所在集合。 ![这里写图片描述][S

    相关

    并查集的作用就是快速判断两个元素是否在同一个集合中,快速将两个集合合并 基本模板 include <iostream> include <a