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

    先贴上参考资料

    1、杭电的并查集课件...

    http://wenku.baidu.com/link?url=IJ10qA1w6APfrbZuF-tq0Rl_-SAM4_LyXBLpkAn_GUwlBhaFRZfMZN_XdUlXkwIhRW1SCp3tJBkqtaU7kOzOq33ENgByKAgHA3jtkKzTQ97

    2、相关博客...

    http://hi.baidu.com/czyuan_acm/item/13cbd3258c29e20d72863edf

    http://www.cppblog.com/yuan1028/archive/2011/02/13/139990.html


    并查集,顾名思义,就是做 “并” 和 “查” 两件事的。我们用到并查集基本都是模拟树形结构的,线形的效率太低。

    先贴上模版

     1 #include<cstdio>
     2 #define MAXN 50005
     3 int father[MAXN], rank[MAXN];
     4 void init(int n)
     5 {
     6   for (int i = 1; i <= n; ++i)
     7   {
     8     father[i] = i;
     9     rank[i] = 0;
    10   }
    11 }
    12 int find(int x)
    13 {
    14   if (father[x] != x)
    15   {
    16     father[x] = find(father[x]);
    17   }
    18   return father[x];
    19 }
    20 void merge(int a, int b)
    21 {
    22   int fa = find(a);
    23   int fb = find(b);
    24   if (rank[fa] < rank[fb])
    25   {
    26     father[fa] = fb;
    27   }
    28   if (rank[a] > rank[fb])
    29   {
    30     father[fb] = fa;
    31   }
    32   if (rank[fa] == rank[fb])
    33   {
    34     father[fb] = fa;
    35     rank[fa]++;
    36   }
    37 }

    1、father[]用来记录此结点的父结点,rank[]用来记录此树的深度

    2、find()函数中用了路径压缩,在寻找某个结点的祖先时,将这条路径上所有结点的父结点更新为祖先结点

    3、merge()函数中,是按秩合并。秩就是树的高度。不过很多时候没有必要按秩合并,也就不用开rank[],直接下面这样就ok

    1 void merge(int a, int b)
    2 {
    3   int fa = find(a);
    4   int fb = find(b);
    5   father[fa] = fb;
    6 }

    练习题:

    1、HDOJ 1213 How Many Tables(水题,直接套模版)

    http://acm.hdu.edu.cn/showproblem.php?pid=1213

    2、HDOJ 1232 畅通工程(同上、、)

    http://acm.hdu.edu.cn/showproblem.php?pid=1232

    3、POJ 1182 食物链(经典问题,里面的公式比较难想、、)

    http://poj.org/problem?id=1182

    下面是AC代码:

     1 #include<cstdio>
     2 #define MAXN 1005
     3 int father[MAXN];
     4 void init()
     5 {
     6   for (int i = 0; i < MAXN; ++i)
     7   {
     8     father[i] = i;
     9   }
    10 }
    11 int find(int n)
    12 {
    13   if (father[n] != n)
    14   {
    15     father[n] = find(father[n]);
    16   }
    17   return father[n];
    18 }
    19 void merge(int a, int b)
    20 {
    21   if (find(a) != find(b))
    22   {
    23     father[find(b)] = find(a);
    24   }
    25 }
    26 int main()
    27 {
    28   int T;
    29   scanf("%d", &T);
    30   while(T--)
    31   {
    32     int n, m, a, b, count = 0;
    33     init();
    34     scanf("%d %d", &n, &m);
    35     for (int i = 0; i < m; ++i)
    36     {
    37       scanf("%d %d", &a, &b);
    38       merge(a, b);
    39     }
    40     for (int i = 1; i <= n; ++i)
    41     {
    42       if (father[i] == i)
    43       {
    44         count++;
    45       }
    46     }
    47     printf("%d\n", count);
    48   }
    49   return 0;
    50 }
    View Code
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #define MAXN 1000
     4 int father[MAXN];
     5 void init()
     6 {
     7   for (int i = 0; i < MAXN; ++i)
     8   {
     9     father[i] = i;
    10   }
    11 }
    12 int find(int n)
    13 {
    14   int r = n;
    15   while(father[r] != r)
    16   {
    17     r = father[r];
    18   }
    19   return r;
    20 }
    21 void merge(int s, int e)
    22 {
    23   int a = find(s);
    24   int b = find(e);
    25   if (a < b)
    26   {
    27     father[b] = a;
    28   }else
    29   {
    30     father[a] = b;
    31   }
    32 }
    33 
    34 int main()
    35 {
    36   int n, m, s, e;
    37   while(scanf("%d", &n) != EOF)
    38   {
    39     int ans = 0;
    40     if (n == 0)
    41     {
    42       exit(0);
    43     }else
    44     {
    45       init();
    46       scanf("%d", &m);
    47       for (int i = 0; i < m; ++i)
    48       {
    49         scanf("%d %d", &s, &e);
    50         merge(s, e);
    51       }
    52       for (int i = 1; i <= n; ++i)
    53       {
    54         if (find(i) == i)
    55         {
    56           ans += 1;
    57         }
    58       }
    59       printf("%d\n", ans-1);
    60     }
    61   }
    62   return 0;
    63 }
    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 using namespace std;
     4 #define MAX 50050
     5 int par[MAX],rel[MAX];
     6 
     7 void init(int n)
     8 {
     9     for(int i=1;i<=n;i++)
    10     {
    11         par[i]=i;
    12         rel[i]=0;
    13     }
    14 }
    15 
    16 int find(int x)
    17 {
    18     if(par[x]==x)    return x;
    19     int tmp=par[x];
    20     par[x]=find(tmp);
    21     rel[x]=(rel[tmp]+rel[x])%3;
    22     return par[x];
    23 }
    24 
    25 void union_set(int x,int y,int px,int py,int d)
    26 {
    27     par[px]=py;
    28     rel[px]=(rel[y]-rel[x]+2+d)%3;
    29 }
    30 
    31 int main()
    32 {
    33     int T,n,m,a,b,pa,pb,k,r;
    34     scanf("%d%d",&n,&m);
    35     {
    36         init(n);
    37         r=0;
    38         for(int i=0;i<m;i++)
    39         {
    40             scanf("%d%d%d",&k,&a,&b);
    41             if(a>n||b>n)    {    r++;    continue;}
    42             if(k==2&&a==b)    {    r++;    continue;}
    43             pa=find(a);
    44             pb=find(b);
    45             if(pa==pb)
    46             {
    47                 if((rel[b]+k+2)%3!=rel[a])    r++;
    48             }
    49             else    union_set(a,b,pa,pb,k);
    50         }
    51         printf("%d\n",r);
    52     }
    53 }
    View Code
  • 相关阅读:
    搭建JavaWeb服务器
    Python网络爬虫相关基础概念
    Python网络爬虫 《http和https协议》
    jupyter环境安装
    js 解密,混淆,逆向
    selenium
    2、JNI说明
    1、Java快速入门
    4、基于JZ2440之编写测试代码处理(处理图片识别人脸)
    3、在编译过程中出现no space left on device
  • 原文地址:https://www.cnblogs.com/grubbyskyer/p/3847553.html
Copyright © 2011-2022 走看看