UVA - 11987 - Almost Union-Find (又是并查集~)

UVA - 11987

Almost Union-Find

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

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

Source

Root :: AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) :: Chapter 3. Data Structures :: Fundamental Data Structures :: Exercises:
Intermediate

Root :: Prominent Problemsetters :: Rujia Liu

Root :: Rujia Liu‘s Presents :: Present 3: A Data Structure Contest

思路:1,3比较好实现,2则有点麻烦,2属于并查集的删除操作,需要另设一组real[]数组来确定元素的实际地址,每删除一个元素,就把这个元素放在最后面。。我本来以为直接把p指向q的根就行了,但发现这是错的。如果p是叶子结点,那可以,但如果是某个集合的根呢。我们只是要把这一个元素移掉,如果直接把p指向q的根,它的叶子节点们也过去啦。。。而如果另设一组real数组的话就可以将影响降为0啦。。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;

const int maxn = 200005;
int pa[maxn], real[maxn], cnt[maxn];
int n, m, vnum;
LL sum[maxn];

int find(int x) {
	return pa[x] != x ? pa[x] = find(pa[x]) : x;
}

void Union(int a, int b) {
	int a1 = find(real[a]), b1 = find(real[b]);
	pa[a1] = b1;
	sum[b1] += sum[a1];
	cnt[b1] += cnt[a1];
}

void Move(int a) {
	int t = find(real[a]);
	sum[t] -= a, cnt[t]--;
	real[a] = ++vnum;		//并查集的这里到n了,所以要先++,之前后++的样例没过,检查半天=_=||
	sum[real[a]] = a, cnt[real[a]] = 1, pa[real[a]] = real[a];
}

int main() {
	while(scanf("%d %d", &n, &m) != EOF) {
		for(int i = 0; i <= n; i++) {
			pa[i] = real[i] = sum[i] = i;
			cnt[i] = 1;
		}

		vnum = n;
		int ord, p, q;
		while(m--) {
			scanf("%d", &ord);

			if(ord == 1) {
				scanf("%d %d", &p, &q);
				if(find(real[p]) != find(real[q]))
					Union(p, q);
			}
			else if(ord == 2) {
				scanf("%d %d", &p, &q);
				if(find(real[p]) != find(real[q]))
					Move(p), Union(p, q);
			}
			else if(ord == 3) {
				scanf("%d", &p);
				int tmp = find(real[p]);
				printf("%d %lld\n", cnt[tmp], sum[tmp]);
			}
		}
	}
	return 0;
} 
时间: 2024-10-17 17:57:47

UVA - 11987 - Almost Union-Find (又是并查集~)的相关文章

UVA 3027 Corporative Network 带权并查集、

题意:一个企业要去收购一些公司把,使的每个企业之间互联,刚开始每个公司互相独立 给出n个公司,两种操作 E I:询问I到I它连接点最后一个公司的距离 I I J:将I公司指向J公司,也就是J公司是I公司的上级,距离为abs(I-J)%1000(貌似G++不支持abs,PE了两发) 思路:转化一下题意就行了,首先刚开始的时候每个公司都是独立的,I操作就是并查集中合并操作,将I这课树并到J这个树上, E操作要求的东西就是 I到I的根节点的距离,先看一个没有路径压缩直接暴力的方法把.(本以为不会过的,

Uva 12361 File Retrieval 后缀数组+并查集

题意:有F个单词,1 <= F <=60 , 长度<=10^4, 每次可以输入一个字符串,所有包含该字串的单词会形成一个集合. 问最多能形成多少个不同的集合.集合不能为空. 分析:用后缀数组处理.然后首先考虑一个单词形成一个集合的情况,若该单词是其他单词的字串,则该单词显然不会形成一个集合,那么利用后缀数组, 对于每个单词看能否与其他单词有LCP,且LCP 长度为该单词本身长度. 然后就是多个单词形成集合的情况:比较简单的处理方式就是将h数组值相同的下标集中存储,比如h[x] = h[y

UVA alive 4487 Exclusive-OR(加权并查集+异或运算的理解)

You are not given n non-negative integers X0, X1,..., Xn-1 less than 220, but they do exist, and their values never change. I'll gradually provide you some facts about them, and ask you some questions. There are two kinds of facts, plus one kind of q

UVA 1151 Buy or build(并查集之六)

题意:n个结点,以及m个组合,可以任意选择.求最小花费. 因为组合最多只有8个,可以枚举. #include<stdio.h> #include<math.h> #include<algorithm> #include<string.h> #define MAX 1007 #define INTMAX (int)1e9 using namespace std; struct list_buy { int num; int price; int node[MA

HDU3038 How Many Answers Are Wrong[带权并查集]

How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6336    Accepted Submission(s): 2391 Problem Description TT and FF are ... friends. Uh... very very good friends -_____

HDU--1558--Segment set--并查集***经典***

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3699    Accepted Submission(s): 1394 Problem Description A segment and all segments which are connected with it compose a segment set

uva 11987 Almost Union-Find (并查集)

题目大意: 三个操作. 1. 合并两个集合 2.把第一个元素放到第二个集合里 3.输出集合的数量和和.. 思路分析: 要用p记录这个元素所在集合编号,然后用编号建立并查集. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; int set[111111]; int cn

UVA - 11987 Almost Union-Find[并查集 删除]

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 oper

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

UVA 11987 - Almost Union-Find 题目链接 题意:给定一些集合,操作1是合并集合,操作2是把集合中一个元素移动到另一个集合,操作3输出集合的个数和总和 思路:并查集,关键在于操作2,对于并查集,要去除掉一个结点,如果该结点不是根那就好办了,那么就多开n个结点,每个结点初始父亲都是它的i + n,这样在移动的时候,就不用担心他是根结点了剩下就是普通的带权并查集了 代码: #include <cstdio> #include <cstring> const i