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第一篇博客热乎乎的出炉啦**************

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

  • 相关阅读:
    OpenDaylight及Postman实现VxLAN网络实验
    OpenDaylight的C/S模式实验
    OpenFlow1.3协议基于Mininet部署与验证
    Open vSwitch流表应用实战
    Open vSwitch的VxLAN隧道网络实验
    Open vSwitch的GRE隧道实验网络
    Open vSwitch使用案例扩展实验
    Beta 冲刺(1/7)
    福大软工 · 第十次作业
    福大软工 · BETA 版冲刺前准备(团队)
  • 原文地址:https://www.cnblogs.com/rax-/p/8463380.html
Copyright © 2011-2022 走看看