uva11987(并查集)

题意:

给出数字数量和命令数量;

1 u v 把u和v所在的集合并起来;

2 u v 把u 这个元素放到v所在的集合;

3 u 输出u所在集合的数量,和和;


思路:

1和3都是普通的并查集,但是2的话,如果把一个集合的根移走了,那结构就坏了;

所以执行2的时候要重新创造一个ID代替:

#include <cstdio>
#include <cstring>

const int maxn = 2e5 + 5;

int n, m;
int parent[maxn], cnt[maxn], sum[maxn];
int id[maxn];
int dex;

void init () {

  for (int i = 0; i <= n; i++) {

    cnt[i] = 1;
    sum[i] = id[i] = parent[i] = i;
  }
  dex = n;
}

int getParent (int a) {

  return a == parent[a] ? a: parent[a] = getParent (parent[a]);
}

void Union (int a, int b) {

  int p = getParent (a);
  int q = getParent (b);
  if (p != q) {

    parent[p] = q;
    cnt[q] += cnt[p];
    sum[q] += sum[p];
  }
}

void move (int a) {

  int p = getParent (id[a]);
  cnt[p]--;
  sum[p] -= a;
  id[a] = ++dex;
  parent[dex] = dex;
  cnt[dex] = 1;
  sum[dex] = a;  
}

int main () {

  int type;
  int a, b;
  while (scanf ("%d%d", &n, &m) != EOF) {

    init();
    while (m--) {

      scanf ("%d", &type);
      if (type == 1) {

        scanf ("%d%d", &a, &b);
        Union (id[a], id[b]);
      } else if (type == 2) {

        scanf ("%d%d", &a, &b);
        int p = getParent (id[a]);
        int q = getParent (id[b]);
        if (p != q) {

          move(a);
          Union(id[a], id[b]);
        }
      } else {

        scanf ("%d", &a);
        int p = getParent (id[a]);
        printf ("%d %d\n", cnt[p], sum[p]);
      }
    }
  }
  return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值