• 简单并查集 -- HDU 1232 UVALA 3644 HDU 1856


    并查集模板:

     1 #include<iostream>
     2 using namespace std;
     3 int Rank[1001],x,y;
     4 int v[1001];
     5 //初始化 x 集合
     6 void init(int n)
     7 {
     8     for(int i=0; i<n; i++)
     9     {
    10         v[i]=i;
    11         Rank[i]=0;
    12     }
    13 }
    14 //查找 x 所在的集合
    15 int find_set(int x)
    16 {
    17     if(v[x]!=x) v[x]=find_set(v[x]);
    18     return v[x];
    19 }
    20 ///更新根节点,有可能会暴栈
    21 int mix(int x,int y)
    22 {
    23     int fx,fy;
    24     fx=find_set(x);
    25     fy=find_set(y);
    26     if(fx!=fy)
    27         p[fx]=fy;
    28 }
    29 //合并 x, y 所在的集合,用到路径压缩,按秩合并
    30 void Union(int x,int y)
    31 {
    32     x=find_set(x);
    33     y=find_set(y);
    34     if(Rank[x]>Rank[y])
    35         v[y]=x;
    36     else if(Rank[x]<Rank[y])
    37         v[x]=y;
    38     else if(Rank[x]==Rank[y])
    39     {
    40         v[x]=y;
    41         Rank[y]++;
    42     }
    43 }
    44 int main()
    45 {
    46     return 0;
    47 }
    模板

    计算环的个数,需要缩点:

     1 #include <iostream>
     2 #include <cmath>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <string>
     7 #include <sstream>
     8 #include <algorithm>
     9 #define maxn 100010
    10 #define INF 0x7fffffff
    11 #include <queue>
    12 #define N 1000010
    13 #define ll __int64
    14 #define mem(a,b) memset(a,b,sizeof(a))
    15 #define repu(i, a, b) for(int i = (a); i < (b); i++)
    16 const double PI=-acos(-1.0);
    17 using namesPce std;
    18 ///初始化 x 集合
    19 int P[maxn],Rank[maxn];
    20 void mix()
    21 {
    22     repu(i,0,maxn)
    23     {
    24         P[i]=i;
    25         Rank[i]=0;
    26     }
    27 }
    28 ///查找 x 所在的集合
    29 int find_set(int x)
    30 {
    31     if(P[x]!=x)
    32         P[x]=find_set(P[x]);
    33     return P[x];
    34 }
    35 ///缩点,合并 x, y 所在的集合,用到路径压缩,按秩合并
    36 void Union(int x,int y)
    37 {
    38     x=find_set(x);
    39     y=find_set(y);
    40     if(Rank[x]>Rank[y])
    41         P[y]=x;
    42     else if(Rank[x]<Rank[y])
    43         P[x]=y;
    44     else if(Rank[x]==Rank[y])
    45     {
    46         P[x]=y;
    47         Rank[y]++;
    48     }
    49 }
    50 int main()
    51 {
    52     int x,y;
    53     while(scanf("%d",&x) == 1)
    54     {
    55         mix();
    56         int refu = 0;
    57         while(x!=-1)
    58         {
    59             scanf("%d",&y);
    60             x = find_set(x);
    61             y = find_set(y);
    62             if(x == y)///如果同一个根节点,就是环
    63                 ++refu;
    64             else
    65                 Union(x,y);
    66             scanf("%d",&x);
    67         }
    68         printf("%d
    ",refu);
    69     }
    70     return 0;
    71 }
    UVALA3644 find_set + Union

    计算联通块的个数

    题意:n个结点,m条边,求再连几条边能使得全部结点连通;

    思路:并查集,求该图中有几个连通分支,然后连通块的个数-1;

     1 #include<iostream>
     2 #include<string>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 #include<cmath>
     8 using namespace std;
     9 int p[50001];
    10 int n,m;
    11 int a,b;
    12 int find_set(int x)
    13 {
    14     return p[x]==x?x:find_set(p[x]);
    15 }
    16 void mix(int x,int y)
    17 {
    18     int fx,fy;
    19     fx=find_set(x);
    20     fy=find_set(y);
    21     if(fx!=fy)
    22         p[fx]=fy;
    23 }
    24 int main()
    25 {
    26     int cas=1;
    27     while(scanf("%d",&n)&&n)
    28     {
    29         scanf("%d",&m);
    30         int count=0;
    31         for(int i=1; i<=n; i++)
    32             p[i]=i;
    33         for(int j=1; j<=m; j++)
    34         {
    35             scanf("%d%d",&a,&b);
    36             mix(a,b);
    37         }
    38         for(int i=1; i<=n; i++)
    39             if(p[i]==i) count++;
    40         printf("%d
    ",count-1);
    41     }
    42     return 0;
    43 }
    HDU 1232 find_set + mix

    计算每个连通块个数,取最大:

     1 #include<cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 using namespace std;
     6 struct A
     7 {
     8     int num,pre;
     9 } Set[10000011];
    10 void init(int n)///初始化
    11 {
    12     int i;
    13     for(i=1; i<=n; i++)
    14     {
    15         Set[i].num=1;
    16         Set[i].pre=i;
    17     }
    18 }
    19 int Find(int k)///找根节点
    20 {
    21     if(Set[k].pre==k)
    22         return k;
    23     return Set[k].pre = Find(Set[k].pre);
    24 }
    25 int main()
    26 {
    27     int n,maxn,ans,i,f1,f2;
    28     int x[100011],y[100011];
    29     while(~scanf("%d",&n))
    30     {
    31         if(n==0)
    32         {
    33             printf("1
    ");
    34             continue;
    35         }
    36         maxn=0;
    37         for(i=1; i<=n; i++)
    38         {
    39             scanf("%d%d",&x[i],&y[i]);
    40             maxn = max(maxn,max(x[i],y[i]));
    41         }
    42         init(maxn);
    43         for(i=1; i<=n; i++)
    44         {
    45             f1=Find(x[i]);
    46             f2=Find(y[i]);
    47             if(f1!=f2)
    48             {
    49                 Set[f1].pre=f2;
    50                 Set[f2].num += Set[f1].num;///把该节点的子节点加上
    51             }
    52         }
    53         ans=0;
    54         for(i=1; i<=maxn; i++)
    55             ans=max(ans,Set[i].num);
    56         printf("%d
    ",ans);
    57     }
    58     return 0;
    59 }
    HDU 1856 find_set
  • 相关阅读:
    Jupyter notebook 读取文件的问题
    机器学习-数据清洗和特征选择
    机器学习-逻辑回归
    Java教程
    13.并发编程
    redis 实现
    CyclicBarrier介绍
    Future模式衍生出来的更高级的应用
    并发编程 futuretask
    整理POST请求方式
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4526815.html
Copyright © 2020-2023  润新知