码迷,mamicode.com
首页 > 其他好文 > 详细

UVA - 11987 Almost Union-Find(带删除的并查集)

时间:2015-08-26 17:59:29      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:acm   并查集   uva   

Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

 Status

Description

技术分享

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!

 

带删除的并查集.

操作2实际上是将p从原来的集合中删除,再加入到q所在的集合中。

并查集没有删除的操作,于是换个思路,让p点在其原来的集合中的影响为0,在开辟一个新的节点作为编号为p的节点,加入q所在集合。

用id[i]=ii代表数字i当前的位置,每次删除把id[i]指向其他位置,原来的位置舍去。


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int MAXN = 200000+100;
int parent[MAXN];
int cnt[MAXN];
int sum[MAXN];
int n, m;
int dex;
int id[MAXN];

void make_set()
{
	dex = n;
	for (int i = 0; i <= n; i++)
	{
		parent[i] = i;
		cnt[i] = 1;
		sum[i] = i;
		id[i] = i;
	}
}

int find_set(int t)
{
	if (parent[t] == t)
		return t;
	else
		return parent[t] = find_set(parent[t]);
}

void union_set(int a, int b)
{
	int t1 = find_set(a);
	int t2 = find_set(b);
	if (t1 != t2)
	{
		parent[t2]=t1;
		cnt[t1] += cnt[t2];
		sum[t1] += sum[t2];
	}
}

void move(int a)
{
	int p = find_set(id[a]);
	cnt[p]--;
	sum[p] -= a;         //消除该位置的点在原来集合中的影响
	id[a] = ++dex;       //开辟新的位置表示这个编号的点
	parent[dex] = dex;
	cnt[dex] = 1;
	sum[dex] = a;
}

int main()
{
	while (scanf("%d%d", &n, &m) != EOF)
	{
		make_set();
		int op;
		int a, b;
		while (m--)
		{
			scanf("%d", &op);
			if (op == 1)
			{
				scanf("%d%d", &a, &b);
				union_set(id[a], id[b]);
			}
			else if (op == 2)
			{
				scanf("%d%d", &a, &b);
				int t1 = find_set(id[a]);
				int t2 = find_set(id[b]);
				if (t1 != t2)
				{
					move(a);              //从原来集合中移除
					union_set(id[a], id[b]);   //合并到新的集合中
				}
			}
			else
			{
				scanf("%d", &a);
				int p = find_set(id[a]);
				printf("%d %d\n", cnt[p], sum[p]);
			}
		}
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA - 11987 Almost Union-Find(带删除的并查集)

标签:acm   并查集   uva   

原文地址:http://blog.csdn.net/qq_18738333/article/details/48005681

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!