uva 11987 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).
Output
For each type-3 command, output 2 integers: the number of elements and the sum of elements.
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}
Sample Input
5 7 1 1 2 2 3 4 1 3 5 3 4 2 4 1 3 4 3 3
Sample Output
3 12 3 7 2 8

点击打开链接

题意:

初始时,一共有n个元素的组合1,2,3....n

给出三个操作

1 p q:合并p,q所在的集合

2 p q:把p移动到q所在的集合

3 p:输出p所在的集合的元素的个数,集合元素的总和;

思路:带权并查集;

#include<stdio.h>
int pre[200000+10],a[200000+10],b[200000+10];
int find(int x)
{
	int r=x;
	while(r!=pre[r])
		r=pre[r];
	int i=x,j;
	while(i!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}
int main()
{
	int m,n,i,k,p1,p2,p;
	while(scanf("%d %d",&n,&m)!=EOF)
	{
		for(i=0;i<=n;i++) 
		{
			pre[i]=pre[i+n]=i+n;
			a[i]=a[i+n]=1;
			b[i]=b[i+n]=i;
		}
		while(m--)
		{
			scanf("%d",&k);
			if(k==1)
			{
				scanf("%d %d",&p1,&p2);
				int fx=find(p1);
				int fy=find(p2);
				if(fx!=fy)
				{
					pre[fx]=fy;
					a[fy]+=a[fx];
					b[fy]+=b[fx];
				}
			}
			else if(k==2)
			{
				scanf("%d %d",&p1,&p2);
				int fx=find(p1);
				int fy=find(p2);
				if(fx!=fy)
				{
					pre[p1]=fy;
					a[fy]++;
					a[fx]--;
					b[fy]+=p1;
					b[fx]-=p1;
				}
			}
			else if(k==3)
			{
				scanf("%d",&p);
				printf("%d %d\n",a[find(p)],b[find(p)]);
			}
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值