zoukankan      html  css  js  c++  java
  • 并查集——元素的合并与删除

    一、问题描述 题目链接

    有n个节点(1≤n≤100000),进行如下两种操作:

    (1) M a b, 把a、b合并

    (2)S  a, 把a分离出来

    进行M(1≤M≤1000000)次操作,问最后有几个组?

    二、解题思路

    用并查集来实现,我们都知道并查集的合并操作很容易实现,而从集合中移出一个元素却很难。

    这样想,移出元素相当于建立一个新的集合,我们只需将其指向一个独立的节点。这对于叶子节点容易操作,但如果是中间节点(或根节点),则会导致原集合断开。

    我们将节点编号为0~n-1,将他们的根节点初始化为n~2n-1,这样保证了节点0~n-1都是叶子节点。同时将所有的移出节点分别指向2n~2n+m。最后查询0~n-1所在的不同的集合数。

    三、代码实现

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdbool>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 100000 + 10;
     9 const int maxk = 1000000 + 10;
    10 int n, qcnt;
    11 int fa[2 * maxn + maxk];
    12 bool vis[2 * maxn + maxk];    //注意数组范围,2n+最大查询数
    13 
    14 void init()
    15 {
    16     memset(vis, false, sizeof(vis));
    17     for (int i = 0; i < n; i++)
    18         fa[i] = i + n;
    19     for (int i = n; i < 2 * n + qcnt; i++)
    20         fa[i] = i;
    21 }
    22 
    23 int findset(int x)
    24 {
    25     if (x != fa[x])
    26         return fa[x] = findset(fa[x]);
    27     return fa[x];
    28 }
    29 
    30 void unite(int x, int y)
    31 {
    32     int rx = findset(x);
    33     int ry = findset(y);
    34 
    35     fa[rx] = ry;
    36 }
    37 
    38 int main()
    39 {
    40     int kase = 0;
    41     while (scanf("%d%d",&n,&qcnt) == 2 && (n || qcnt))    //题目描述有误,可能存在n>0,qcnt = 0的情况
    42     {
    43         init();
    44         int cur = 2 * n;
    45         while (qcnt--)
    46         {
    47             char order[3];
    48             int a, b;
    49             scanf("%s%d", order, &a);
    50             if (order[0] == 'M')
    51             {
    52                 scanf("%d", &b);
    53                 unite(a, b);
    54             }
    55             if (order[0] == 'S')
    56             {
    57                 fa[a] = cur;cur++;
    58             }
    59         }
    60         int ans = 0;
    61         for (int i = 0; i < n; i++)
    62         {
    63             int root = findset(i);
    64             if (!vis[root])
    65             {
    66                 ans++;
    67                 vis[root] = true;
    68             }
    69         }
    70         printf("Case #%d: %d
    ", ++kase, ans);
    71     }
    72 }
  • 相关阅读:
    HTTP协议图--概述
    HTTP协议图--HTTP 工作过程
    HTTP协议图--HTTP 协议基础
    7万网站用户行为大数据分析
    80万商城运营大数据分析
    文本挖掘之词云及个性化词云
    数据分析:某地医院药品销售业务数据分析
    示例python 批量操作excel统计销售榜品牌及销售额
    目标用户偏好指数Target Group Index分析
    linux 下部署web 程序
  • 原文地址:https://www.cnblogs.com/lfri/p/9484005.html
Copyright © 2011-2022 走看看