zoukankan      html  css  js  c++  java
  • 并查集

    并查集用来处理集合之间的关系,动态地维护和处理集合元素之间复杂的关机,快速合并,反复查找某元素所在的集合。

    用一种通俗的说法就是1号和2号是亲戚,2号和3号是亲戚,则1号和3号是亲戚

    类似于上图

    **************************************

    根据书上所述

    应该有两种方法

    不要在意上面的字啦。。。。。。。。。。。。

    最最最上面的图方法会超时

    下面这幅就高大上了,人家不会超时

    上面是串成糖葫芦式,下面名曰路径压缩。。其实就是所有子子孙孙都黏在他们祖先上

    **********************************************

    例题

    •        【例4-9】、亲戚(relation)

    •        【问题描述】

    •        或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。为了将问题简化,你将得到一些亲戚关系的信息,如Marry和Tom是亲戚,Tom和Ben是亲戚,等等。从这些信息中,你可以推出Marry和Ben是亲戚。请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

    •        【输入格式】

    •        输入由两部分组成。

    •        第一部分以N,M开始。N为问题涉及的人的个数(1≤N≤20000)。这些人的编号为1,2,3,…, N。下面有M行(1≤M≤1 000 000),每行有两个数ai, bi,表示已知aibi是亲戚。

    •        第二部分以Q开始。以下Q行有Q个询问(1≤Q≤1 000 000),每行为ci, di,表示询问cidi是否为亲戚。

    •        【输出格式】

    •        对于每个询问ci, di,输出一行:若ci和di为亲戚,则输出“Yes”,否则输出“No”。

    •        【输入样例】

    •          10 7

    •          2 4

    •          5 7

    •          1 3

    •          8 9

    •          1 2

    •          5 6

    •          2 3

    •          3

    •          3 4

    •          7 10

    •          8 9

    •        【输出样例】

    •          Yes

    •          No

    •          Yes

    ***********************************

    超时的那种

     1     #include<iostream>
     2       #include<cstdio>
     3       using namespace std;
     4       #define maxn 20001
     5       int father[maxn];
     6       int m,n,i,x,y,q;
     7       /*
     8       int find(int x)                  //用非递归的实现
     9       {
    10           while (father[x] != x) x = father[x];
    11           return x;
    12       }
    13       */
    14       int find(int x)                   //用递归的实现
    15       {
    16           if (father[x] != x) return find(father[x]);
    17           else return x;
    18       }  
    19       void unionn(int r1,int r2)
    20       {
    21           father[r2] = r1;
    22       }
    23             int main()
    24       {
    25           freopen("relation.in","r",stdin);
    26           freopen("relation.out","w",stdout);
    27           cin >> n >> m;
    28           for (i = 1; i <= n; i++)
    29               father[i] = i;           //建立新的集合,其仅有的成员是i
    30           for (i = 1; i <= m; i++)
    31           {
    32               scanf("%d%d",&x,&y);
    33               int r1 = find(x);
    34               int r2 = find(y);
    35               if (r1 != r2) unionn(r1,r2);
    36           }    
    37           cin >> q;
    38           for (i = 1; i <= q; i++)
    39           {
    40               scanf("%d%d",&x,&y);
    41               if (find(x) == find(y)) printf("Yes
    ");
    42                   else printf("No
    ");
    43      }
    44           return 0;
    45   }

    **************************************************************

    路径压缩就可以减少时间复杂度

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstring>
     5 using namespace std;
     6 #define maxn 20001
     7 int father[maxn];
     8 int m,n,i,x,y,q;
     9 int find(int x)
    10 {
    11     if(father[x] != x)
    12     father[x] = find(father[x]);
    13     return father[x];
    14 }                      //递归 
    15 void unionm(int x,int y)
    16 {
    17     x = find(x);
    18     y = find(y);
    19     father[y] = x;
    20 }          //指向祖先 
    21 int main()
    22 {
    23     cin >> n >> m;
    24     for(int i = 1;i <= n;i++)
    25     {
    26         father[i] = i;
    27      } 
    28      for(int i = 1;i <= m;i++)
    29      {
    30          scanf("%d %d",&x,&y);
    31          int r1 = find(x);
    32          int r2 = find(y);
    33          if(r1 != r2)
    34          {
    35              unionm(r1,r2);
    36          }
    37          cin >> q;
    38          for(int i = 1;i <= q,i++)
    39          {
    40              scanf("%d %d",&x,&y);
    41              if(find(x) == find(y))
    42              printf("Yes
    ");
    43              else
    44              printf("No
    ");
    45              
    46          }                //比较 
    47          return 0;
    48      }
    49  } 

    **********************************

    odk第一篇博客热乎乎的出炉啦**************

    撒花✿✿ヽ(°▽°)ノ✿

  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/rax-/p/8463380.html
Copyright © 2011-2022 走看看