简单并查集

来源:互联网 发布:大数据产生的背影 题 编辑:程序博客网 时间:2024/04/20 14:57

Description

Download as PDF

Problem A

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 71 1 22 3 41 3 53 42 4 13 43 3

Output for the Sample Input

3 123 72 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}

题意:给你三种操作,合并,删点,查询该点所在的集合中元素的个数和所有元素的和

思路:刚开始做,考虑到当删除根节点时,将根节点指向root++,然后再将根节点的孩子指向root

例如:本来1,3 ,4在一个集合(集合最大值为4)现在你想执行2 4 2这个操作,那么你应把4节点删除然后rank[]和sum[]向应的减少,鼓捣了半天竟然超时。 想了想,在建立一个far1【】对根进行操作。思路还是上面的思路,只是当转移的时候,将far1[]中对应的值和你想要删除的点和另一个点重新建立关系,那么原来的那个节点就成了虚点。

#include<iostream>
#include<algorithm>
#include<cstdio>
#define max 100100*2
using namespace std;
int m,n;
int far[max];
int far1[max];
int sum[max];
int rank[max];
int root;
int c,a,b;
void init(int x)
{


    for(int i=1; i<=x; i++)
    {
        far[i]=i;
        far1[i]=i;
        rank[i]=1;
        sum[i]=i;
    }
}
int find_set(int n)
{
    int tem;
    if(n==far[n])
        return n;
    far[n]=find_set(far[n]);
    return far[n];
}
void Union_set1(int a,int b)
{
    int x=find_set(far1[a]);
    int y=find_set(far1[b]);
    if(x==y)
        return ;
    sum[y]+=sum[x];
    far[x]=y;
    rank[y]+=rank[x];
}
void Union_set2(int a,int b)
{


    int x=find_set(far1[a]);
    int y=find_set(far1[b]);
    if(x==y)
        return ;
    int xx=far1[a];
    rank[find_set(xx)]--;
    sum[find_set(xx)]-=a;
    far1[a]=root++;
    sum[far1[a]]=a;
    rank[far1[a]]=1;
    far[far1[a]]=far1[a];
    Union_set1(a,b);
}
int main()
{
    int ans1,ans2;
    int tem;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        root=m+1;
        init(m);
        while(n--)
        {
            scanf("%d",&c);
            switch(c)
            {
            case 1:
                scanf("%d%d",&a,&b);
                Union_set1(a,b);
                break;
            case 2:
                scanf("%d%d",&a,&b);
                Union_set2(a,b);
                break;
            case 3:
                scanf("%d",&a);
                tem=find_set(far1[a]);
                printf("%d %d\n",rank[tem],sum[tem]);
                break;
            }
        }
    }
    return 0;
}

原创粉丝点击