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 q

Union the sets containing p and q. If p and q are already in the same set, ignore this command.

2 p q

Move p to the set containing q. If p and q are already in the same set, ignore this command

3 p

Return the number of elements and the sum of elements in the set containing p.

Initially, the collection contains n sets: {1}, {2}, {3}, ..., {n}.

Input

There are several test cases. Each test case begins with a line containing two integers n and m (1<=n,m<=100,000), the number of integers, and the number of commands. Each of the next m lines contains a command. For every operation, 1<=p,q<=n. The input is terminated by end-of-file (EOF). The size of input file does not exceed 5MB.

Output

For each type-3 command, output 2 integers: the number of elements and the sum of elements.

Sample Input

5 7
1 1 2
2 3 4
1 3 5
3 4
2 4 1
3 4
3 3

Output for the Sample Input

3 12
3 7
2 8

Explanation

Initially: {1}, {2}, {3}, {4}, {5}

Collection after operation 1 1 2: {1,2}, {3}, {4}, {5}

Collection after operation 2 3 4: {1,2}, {3,4}, {5} (we omit the empty set that is produced when taking out 3 from {3})

Collection after operation 1 3 5: {1,2}, {3,4,5}

Collection after operation 2 4 1: {1,2,4}, {3,5}



Rujia Liu‘s Present 3: A Data Structure Contest Celebrating the 100th Anniversary of Tsinghua University
Special Thanks: Yiming Li
Note: Please make sure to test your program with the gift I/O files before submitting!

ac代码:

#include<stdio.h>
int f[200005],id[200005],c[200005],sum[200005];
int dex;
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
void join(int x,int y)
{
    int fx=find(x),fy=find(y);
    if(fx!=fy){
        f[fy]=fx;
        c[fx]+=c[fy];
        sum[fx]+=sum[fy];
    }
}
void del(int x)
{
    int fx=find(id[x]);
    c[fx]--;
    sum[fx]-=x;
    id[x]=++dex;
    f[dex]=dex;
    c[dex]=1;
    sum[dex]=x;    //并查集删除操作
}
int main()
{
    int n,q,x,y,z,i;
    while(~scanf("%d%d",&n,&q)){
        dex=n;
        for(i=1;i<=n;i++){
            f[i]=i;
            id[i]=i;
            c[i]=1;
            sum[i]=i;
        }
        for(i=1;i<=q;i++){
            scanf("%d",&x);
            if(x==1){
                scanf("%d%d",&y,&z);
                join(id[y],id[z]);
            }
            else if(x==2){
                scanf("%d%d",&y,&z);
                int fy=find(id[y]);
                int fz=find(id[z]);
                if(fy!=fz){
                    del(y);
                    join(id[y],id[z]);
                }
            }
            else{
                scanf("%d",&y);
                int fy=find(id[y]);
                printf("%d %d\n",c[fy],sum[fy]);
            }
        }
    }
    return 0;
}
时间: 2024-08-30 14:19:06

Almost Union-Find 并查集的删除的相关文章

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

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_

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

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 <cstr

[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,也可以用数组标记信件是归在哪个文件夹

&lt;算法&gt;&lt;Union Find并查集&gt;

Intro 想象这样的应用场景:给定一些点,随着程序输入,不断地添加点之间的连通关系(边),整个图的连通关系也在变化.这时候我们如何维护整个图的连通性(即判断任意两个点之间的连通性)呢? 一个比较简单的solution是每个点都有一个便签,标记它属于哪个连通子图.这种做法就有一个很明显的问题 -- 牵一发而动全身,因为每个节点所属的组号(标签)都是单独记录,各自为政的,没有将它们以更好的方式组织起来,当涉及到修改的时候,除了逐一通知.修改,别无他法.所以现在的问题就变成了,如何将节点以更好的方式

朋友(并查集的删除操作 可看作是插入操作的逆序)

小 z 被选为他们村的村长, 现在小 z 调查他们村上的关系. 如果村民 a 和村民 b 是朋友, 村民 b 和村民 c 是朋友, 那么村民 a 和村民 c 也是朋友. 那么村上的村民就会形成一个"朋友" 团队, 现在小 z 想知道他们村长有多少个这样的团队. 同时, 他们村会有人离开村子到城里谋求发展, 那么小 z 也想知道, 当他们离开后村上的"朋友" 团队.★数据输入输入第一行包括两个整数, N, M. N 表示一共有 N 个人, M 表示一个共有M 对关系.