uva 11987 - Almost Union-Find(并查集)

本文介绍了一种名为 AlmostUnion-Find 的数据结构实现,该结构支持集合的合并、元素移动及集合信息查询等操作,并提供了一个具体的编程示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=66&page=show_problem&problem=3138

2、题目大意;

给定一些操作:
1 a b是合并两个数a b(直接用merge(a,b))

2 a b是将a从原来所在集合中删除,将a移动到b所在的集合中(delete(a),merge(a,b))

3 a 是查询a所在的集合有 多少个数,以及这些数的和,需要打印

3、题目:

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

4、代码:

#include<stdio.h>
#include<string.h>
#define N 200005
int set[N];
char op;
int flag[N];
long long sum[N];
int count[N];
int id[N];
int cnt;
int find(int x)
{
    int r=x;
    while(r!=set[r])
        r=set[r];
    int i=x;
    while(i!=r)
    {
        int j=set[i];
        set[i]=r;
        i=j;
    }
    return r;
}
void Delete(int x)
{
    int fx = find(id[x]);
    count[fx]--;
    sum[fx]-= x;
    id[x]=++cnt;
    set[id[x]]=id[x];
    count[id[x]] = 1;
    sum[id[x]] = x;
}
void merge(int x,int y)
{
    int fx=find(id[x]);
    int fy=find(id[y]);
    //if(fx!=fy)
    //{
        set[fx]=fy;
        count[fy]+=count[fx];
        sum[fy]+=sum[fx];
   //}
}
int main()
{
    int n,m,a,b,c,d,e;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        getchar();
        cnt=n;//赋值错了
        for(int i=1; i<=n; i++)
        {
            set[i]=i;
            count[i]=1;
            sum[i]=i;
            id[i]=i;
        }
        for(int i=1; i<=m; i++)
        {
            scanf("%c",&op);
            if(op=='1')
            {
                scanf("%d%d",&a,&b);
                getchar();
                 if(find(id[a])!=find(id[b]))
                merge(a,b);
                //merge(a,b);
            }
            else if(op=='2')
            {
                scanf("%d%d",&c,&d);
                //merge(id[c],id[d]);
                getchar();
                if(find(id[c])!=find(id[d]))
                {Delete(c);
                merge(c,d);
                }
            }
            else if(op=='3')
            {
                //printf("****\n");
                scanf("%d",&e);
                getchar();
                //printf("e==%d\n",e);
                int ee=find(id[e]);
                printf("%d %lld\n",count[ee],sum[ee]);
            }
        }
    }
    return 0;
}

/*

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


*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值