• 并查集


    幷查集是一種很diao的數據結構,應用的很典型的栗子就是找共同的祖先,或者說是一組數字指向同一個根,是一種樹形的結構;

    具體可以看一下這裡:別人家的博客

    比如,給出幾個數,作為同學的編號,他們的初始父親是一個叫-1的節點:

    -1 -1  -1  -1

    1 2 3 4

    如果他們有著同樣的興趣愛好,那麼就可以把它們合併到同一個父親節點上,比如合併到1:

    1 1 1 1

    1 2 3 4

    這樣就形成了一個樹形的結構

      1

    2 3 4

    本來1234是四個人的,現在變成了同一個興趣小組,所以幷查集可以看作是一個合併的過程,下面看他的具體應用:

    只要理解上面的就沒有問題!

    poj 2524. Ubiquitous Religions

     1 // poj 2524. Ubiquitous Religions
     2 // 并查集 求最多有多少个祖先
     3 // references:
     4 // no
     5 #include <iostream>
     6 #include <cstdio>
     7 #include <cstring>
     8 #include <algorithm>
     9 
    10 using namespace std;
    11 
    12 int p[50005];
    13 int ans;
    14 
    15 void init()
    16 {
    17     memset(p, -1, sizeof(p));
    18 }
    19 
    20 int find(int x)
    21 {
    22     return p[x] == -1 ? x : p[x] = find(p[x]);
    23 }
    24 
    25 void union_set(int u, int v)
    26 {
    27     int x = find(u);
    28     int y = find(v);
    29     if(x != y)
    30     {
    31         p[x] = y;
    32         ans--;
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     int n, m, k = 1;
    39     while(scanf("%d%d", &n, &m) != EOF, n, m)
    40     {
    41         ans = n;
    42         init();
    43         int u, v;
    44         for(int i=0; i<m; i++)
    45         {
    46             scanf("%d%d", &u, &v);
    47             union_set(u, v);
    48         }
    49         printf("Case %d: %d
    ", k++, ans);
    50     }
    51     return 0;
    52 }

    poj 1611.The Suspects

     1 // poj 1611.The Suspects
     2 // 并查集
     3 // references:
     4 // no
     5 #include <iostream>
     6 #include <cstdio>
     7 #include <cstring>
     8 #include <algorithm>
     9 
    10 using namespace std;
    11 
    12 const int N = 30005;
    13 int n, m;
    14 int p[N];
    15 int num[N];
    16 
    17 void init()
    18 {
    19     for(int i=0; i<n; i++)
    20     {
    21         p[i] = -1;
    22         num[i] = 1;        //记录该点为祖先的后代个数 
    23     }
    24 }
    25 
    26 int find(int x)
    27 {
    28     return p[x] == -1 ? x : p[x] = find(p[x]);
    29 }
    30 
    31 void union_set(int u, int v)
    32 {
    33     int x = find(u);
    34     int y = find(v);
    35     if(x != y)
    36     {
    37         p[x] = y;
    38         num[y] += num[x];    //注意这里是加上x的num[],不只是++;    
    39     }    
    40 }
    41 
    42 int main()
    43 {
    44     while(scanf("%d%d", &n, &m) != EOF, n)
    45     {
    46         init();
    47         for(int i=0; i<m; i++)
    48         {
    49             int k, u, v;
    50             scanf("%d", &k);
    51             scanf("%d", &u);
    52             for(int j=1; j<k; j++)
    53             {
    54                 scanf("%d", &v);
    55                 union_set(u, v);    //都跟第一个合并 
    56                 //u = v;
    57             }
    58         }
    59         int x = find(0);    //找到0的祖先 
    60         printf("%d
    ", num[x]);
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    字符串 列表 元组 字典 集合3.4列表
    判断语句和循环语句2.12 for循环
    字符串 列表 元组 字典 集合3.3字符串常见操作
    判断语句和循环语句2.13 break和continue
    字符串 列表 元组 字典 集合3.5列表的常见操作
    c#生成json类
    JQuery UI Datepicker中文显示的方法
    ReportViewer无法直接打印的问题
    C++与SQL数据库 使用基础
    WM 6.0 中的设备控制启用设备与禁用设备
  • 原文地址:https://www.cnblogs.com/dominjune/p/4720262.html
Copyright © 2020-2023  润新知