• ACM__并查集


    并查集是树型的数据结构,处理不想交集合

    主要解决查找和合并的问题

    步骤:

    初始化

    把每个点所在的集合初始化为自身 复杂度为O(N)

    查找

    查找元素所在的集合,即根节点

    合并

    将两个元素所在的集合合并在一个集合

     1 #include<cstdio>
     2 int anc[105];
     3 void init(int n)
     4 {
     5   for(int i=1;i<=n;i++)
     6         anc[i]=i;
     7 }//初始化,每个点的祖先都是它自己
     8 int find_(int x)
     9 {
    10     while(anc[x]!=x)//根节点的祖先是它自己,所以当anc[x]==x时,找到了祖先,跳出循环
    11         x=anc[x];
    12     return x;
    13 }//查找该点的根节点
    14 void union_(int x,int y)
    15 {
    16     int fx,fy;
    17     fx=find_(x);
    18     fy=find_(y);
    19     if(fy!=fx)//如果y的根节点不等于x的根节点,那么把x的根节点当作y的根节点的father
    20         anc[fy]=fx;
    21 }//合并两个集合 
    22 int main()
    23 {
    24     int n,m;
    25     scanf("%d %d",&n,&m);//有n个点,m条边
    26     for(int i=1;i<=m;i++)
    27     {
    28         scanf("%d %d",&a,&b);
    29         union_(a,b);
    30     }
    31 }

    例题:

    畅通工程

    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 
     

    Input

    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
    注意:两个城市之间可以有多条道路相通,也就是说 
    3 3 
    1 2 
    1 2 
    2 1 
    这种输入也是合法的 
    当N为0时,输入结束,该用例不被处理。 
     

    Output

    对每个测试用例,在1行里输出最少还需要建设的道路数目。 
     

    Sample Input

    4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
     

    Sample Output

    1 0 2 998
     
    分析:问最少需要建设几条路才能使所有的城市都能有道路连通,那么只需要求有几个不同集合,道路条数即是集合数-1;
     1 #include<cstdio>
     2 int t[1005];
     3 int find_(int x)
     4 {
     5     while(x!=t[x])
     6         x=t[x];
     7     return x;
     8 }
     9 void union_(int x,int y)
    10 {
    11     int fx,fy;
    12     fx=find_(x);
    13     fy=find_(y);
    14     if(fx!=fy)
    15         t[fx]=fy;
    16 }
    17 int main()
    18 {
    19     int n,m,a,b;
    20     while(~scanf("%d",&n))
    21     {
    22         if(n==0)
    23             break;
    24         scanf("%d",&m);
    25         for(int i=1; i<=n; i++)
    26         {
    27             t[i]=i;
    28         }
    29         for(int i=1; i<=m; i++)
    30         {
    31             scanf("%d %d",&a,&b);
    32             union_(a,b);
    33         }
    34         int cnt=0;
    35         for(int i=1; i<=n; i++)
    36         {
    37             if(t[i]==i)
    38                 cnt++;
    39         }
    40         printf("%d
    ",cnt-1);
    41     }
    42 }
  • 相关阅读:
    模拟http请求 带 chunked解析办法一
    DLL入口函数
    修复吾爱OD数据窗口双击不出现偏移问题
    PE导入表分析
    持仓盈亏公式
    hadoop工作相关
    zookeeper常用命令
    git使用命令行上传文件
    redis中各种数据类型对应的jedis操作命令
    volatile关键字比较好的解释
  • 原文地址:https://www.cnblogs.com/LLLAIH/p/9674117.html
Copyright © 2020-2023  润新知