• 并查集


    并查集是一种用于处理一些不相交集合(Disjoint Sets)的合并及查询问题的树形数据结构,可以高效的解决多个元素的集合应用问题中:

    合并集合、查询某元素属于某集合的问题

    并查集的基本函数:

    初始化:

    1 void init()//未进行操作时没一个元素的祖先的是他自己
    2 {
    3     for (int i = 1; i <= n; i++)
    4         f[i] = i;
    5 }

    查找:

    1 int find(int x)//如果还没有查找到根节点(f[x]==x)
    2 {               //就不断递归查找x的祖先的祖先(f[x]=find(find[x]))
    3     return f[x] == x ? x : f[x] = find(f[x]);
    4 }

    合并:

    1 void merge(int a, int b)
    2 {
    3     int x = find(a);
    4     int y = find(y);
    5     if (x != y)
    6         f[y] = x;
    7 }

    基础并查集:

    例题:洛谷 P1551 亲戚

     1 #include<iostream>
     2 using namespace std;
     3 const int maxn = 100010;
     4 int n, m, p, f[maxn];
     5 void init()
     6 {
     7     for (int i = 1; i <= n; i++)
     8         f[i] = i;
     9 }
    10 int find(int x)
    11 {
    12     return f[x] == x ? x : find(f[x]);
    13 }
    14 void merge(int a, int b)
    15 {
    16     int x = find(a);
    17     int y = find(b);
    18     if (x != y)
    19         f[y] = x;
    20 }
    21 int main()
    22 {
    23     cin >> n >> m >> p;
    24     init();
    25     for (int i = 1; i <= m; i++)
    26     {
    27         int a, b;
    28         cin >> a >> b;
    29         merge(a, b);
    30     }
    31     for (int i = 1; i <= p; i++)
    32     {
    33         int a, b;
    34         cin >> a >> b;
    35         if (find(a) == find(b))
    36             cout << "Yes" << endl;
    37         else
    38             cout << "No" << endl;
    39     }
    40     return 0;
    41 }

     拓展并查集:

    例题:洛谷 P1525 关押罪犯

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 int n, m;
     6 struct people
     7 {
     8     int u, v, w;
     9 }p[100010];
    10 int f[100010];
    11 int e[100010];
    12 bool cmp(people a, people b)
    13 {
    14     return a.w > b.w;
    15 }
    16 int find(int x)
    17 {
    18     return f[x] == x ? x : f[x] = find(f[x]);
    19 }
    20 void merge(int a, int b)
    21 {
    22     int x = find(a);
    23     int y = find(b);
    24     if (x != y)
    25         f[y] = x;
    26 }
    27 int main()
    28 {
    29     cin >> n >> m;
    30     for (int i = 1; i <= n; i++)
    31         f[i] = i;
    32     for (int i = 1; i <= m; i++)
    33         cin >> p[i].u >> p[i].v >> p[i].w;
    34     sort(p + 1, p + 1 + m, cmp);
    35     for (int i = 1; i <= m; i++)
    36     {
    37         int a = p[i].u;
    38         int b = p[i].v;
    39         if (find(a) == find(b))
    40         {
    41             cout << p[i].w << endl;
    42             return 0;
    43         }
    44         else
    45         {
    46             if (!e[a])
    47             {
    48                 e[a] = b;
    49             }
    50             else
    51             {
    52                 merge(e[a], b);
    53             }
    54             if (!e[b])
    55             {
    56                 e[b] = a;
    57             }
    58             else
    59             {
    60                 merge(e[b], a);
    61             }
    62         }
    63     }
    64     cout << 0 << endl;
    65     return 0;
    66 }

     特殊的并查集:

    例题:P2024 [NOI2001]食物链

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdio>
     5 using namespace std;
     6 const int maxn = 100010;
     7 int n, m;
     8 int ans;
     9 int f[maxn * 3];
    10 void init()
    11 {
    12     for (int i = 1; i <= n * 3; i++)
    13         f[i] = i;
    14 }
    15 int find(int x)
    16 {
    17     return f[x] == x ? x : f[x] = find(f[x]);
    18 }
    19 void merge(int a, int b)
    20 {
    21     int x = find(a);
    22     int y = find(b);
    23     if (x != y)
    24         f[y] = x;
    25 }
    26 int main()
    27 {
    28     cin >> n >> m;
    29     init();
    30     for(int i=1;i<=m;i++)
    31     {
    32         int t, x, y;
    33         cin >> t >> x >> y;
    34         if (x > n || y > n)
    35         {
    36             ans++;
    37             continue;
    38         }
    39         if (t == 1)
    40         {
    41             if (find(x) == find(y + n) || find(x + n) == find(y))
    42             {
    43                 ans++;
    44             }
    45             else
    46             {
    47                 merge(x, y);
    48                 merge(x + n, y + n);
    49                 merge(x + 2 * n, y + 2 * n);
    50             }
    51         }
    52         else
    53         {
    54             if (find(x) == find(y) || find(x) == find(y + n))
    55             {
    56                 ans++;
    57             }
    58             else
    59             {
    60                 merge(x + n, y);
    61                 merge(x + 2 * n, y + n);
    62                 merge(x, y + 2 * n);
    63             }
    64         }
    65     }
    66     cout << ans << endl;
    67     return 0;
    68 }
  • 相关阅读:
    缓存技术2之CDN缓存 大风起
    Nginx入门级 大风起
    利用??运算符简化单件模式代码
    关于THREAD线程中CurrentCulture与CurrentUICulture的学习及疑问
    Lc.exe 已退出,代码 1
    家族荣誉
    检测到有潜在危险的Request.Form值
    FileUpLoad控件的使用
    ASP.NET中DataGrid和DataList控件用法比较
    漫谈DataList的用法
  • 原文地址:https://www.cnblogs.com/HNFOX/p/11392270.html
Copyright © 2020-2023  润新知