UVA11987 - Almost Union-Find (并查集带删除)

题目链接

题目大意:给出三个操作: 1 p q 表示将p q 这两个数所在的集合合并在一起。2 p q表示将p这个数从原有的集合中拿出来放到q所在的集合中。3 p表示查询p所在的集合总共有几个元素,和是多少。

解题思路:并查集。只是并查集中并没有删除的操作。所以就需要将删除的这个点的影响降到0,也就是给删除的点申请一个新的id,以后都是用这个新的id来表示这个点,这样原来的那个集合里的点p就没意义,自然影响就为0.

代码:

#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;
}
时间: 2024-08-29 07:31:27

UVA11987 - Almost Union-Find (并查集带删除)的相关文章

HDU 1035 Robot Motion Union Find 并查集题解

本题的类型我一看就想到使用并查集解了,因为要查找是否有环,这是并查集的典型用法. 但是由于本题数据实在是太水了,故此有人使用直接模拟都过了.这让本题降了个档次. 这里使用并查集解.而且可以根据需要简化并查集函数,代码还是很好打的. #include <stdio.h> #include <vector> #include <string.h> #include <algorithm> #include <iostream> #include &l

POJ 2524 Ubiquitous Religions Union Find 并查集

本题是标准的并查集了,最后利用这些集求有多少独立集. 所以这里也写个标准程序过了. 最后查找独立集合: 看有多少个节点的父母节点是自己的,那么就是独立集合了.自己做自己的父母当然最独立的了,没有任何依赖,呵呵. #include <stdio.h> const int MAX_N = 50001; //const int MAX_M = MAX_N/2 * (MAX_N-1) + 1; int N, M; struct SubSet { int p, r; }; SubSet sub[MAX_

HDU 2473 Junk-Mail Filter (并查集的删除操作)

Problem Description Recognizing junk mails is a tough task. The method used here consists of two steps: 1) Extract the common characteristics from the incoming email. 2) Use a filter matching the set of common characteristics extracted to determine w

POJ 1182 食物链 [并查集 带权并查集 开拓思路]

传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1182 Appoint description:  System Crawler  (2015-01-27) Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物

【并查集&amp;&amp;带权并查集】BZOJ3296&amp;&amp;POJ1182

bzoj1529[POI2005]ska Piggy banks [题目大意] n头奶牛m种语言,每种奶牛分别掌握一些语言.问至少再让奶牛多学多少种语言,才能使得它们能够直接或间接交流? [思路] (n+m)个点,奶牛学会某种语言就合并它和语言的节点.并查集维护联通块,答案为联通块个数-1.水,可是我跳坑了. 我一开始做法是设总的联通块有(n+m)个,然后没合并一次减去1.其实这样是不可行的,因为我们只需要考虑奶牛(即节点1..n)有几个联通块.有可能一些语言根本没有任何奶牛掌握-- 1 #in

Restructuring Company和Almost Union-Find 并查集的区间合并与并查集的删除

Restructuring Company Even the most successful company can go through a crisis period when you have to make a hard decision - to restructure, discard and merge departments, fire employees and do other unpleasant stuff. Let's consider the following mo

Almost Union-Find 并查集的删除

Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operations: 1 p

[HDOJ2473]Junk-Mail Filter(并查集,删除操作,马甲)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2473 给两个操作:M X Y:将X和Y看成一类. S X:将X单独划归成一类. 最后问的是有多少类. 并查集,但是带有删除操作.然而并查集本身不支持删除,网上说可以引入一个id来表示一个点.就好像一个人上网有很多小号一样,假如这个人的小号被封掉并且永久不能解封,还想继续玩下去的话那就重新建一个号,再生成一个id,表示这个id是这个人就好了. 注意在删除操作的时候不能把原来id的pre值重置. 1 /

并查集的删除操作

C - Junk-Mail Filter  HDU - 2473 题目大意:就是一堆信件,然后有两个操作,一个是把一堆信件归在一个文件夹,一个就是把一个信件从文件夹中取出,最后问有多少个文件夹,一开始所有信件都是单独的文件夹. 其实就是一个简单的并查集删除的操作,当删除时就创建新的结点来代替它,要注意的是数组的范围,虽然信件只有10的5次方,但是操作有10的6次方,因为删除时还得创建新节点,所以数组一定要开大,不然不是WR就是TL.最后的输出可以直接用set,也可以用数组标记信件是归在哪个文件夹