FZU - 2155 - 盟国 (带删除的并查集~~)

Problem 2155 盟国

Accept: 140    Submit: 464
Time Limit: 5000 mSec    Memory Limit : 32768 KB

 Problem Description

世界上存在着N个国家,简单起见,编号从0~N-1,假如a国和b国是盟国,b国和c国是盟国,那么a国和c国也是盟国。另外每个国家都有权宣布退盟(注意,退盟后还可以再结盟)。

定义下面两个操作:

“M X Y” :X国和Y国结盟

“S X” :X国宣布退盟

 Input

多组case。

每组case输入一个N和M (1 ≤ N ≤ 100000 , 1 ≤ M ≤ 1000000),N是国家数,M是操作数。

接下来输入M行操作

当N=0,M=0时,结束输入

 Output

对每组case输出最终有多少个联盟,格式见样例。

 Sample Input

5 6
M 0 1
M 1 2
M 1 3
S 1
M 1 2
S 3
3 1
M 1 2
0 0

 Sample Output

Case #1: 3
Case #2: 2






带删除操作的并查集。。


AC代码:

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

const int maxn = 2000005;			//注意这里M可以到1000000,所以maxn要开大点 
int pa[maxn], real[maxn];//用real数组标记每个点的真实位置,删除一个点后只需将其放于末尾即可 
int vis[maxn];

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

int main() {
	int n, m, cas = 1;
	while(scanf("%d %d", &n, &m) == 2 && (n || m)) {
		for(int i=0; i<n; i++) 
			pa[i] = real[i] = i;
		memset(vis, 0, sizeof(vis));
		
		char fun[5];
		int a, b, sum = n;
		while(m--) {	
			scanf("%s", fun);
			if(fun[0] == 'M') {
				scanf("%d %d", &a, &b);
				int x = find(real[a]), y = find(real[b]);
				if(x != y) pa[x] = y;
			} else {
				scanf("%d", &a);
				pa[sum] = sum;
				real[a] = sum++;	//相当于把a从原来的位置删除,记录新的位置 
			}
		}
		
		int ans = 0;
		for(int i=0; i<n; i++) {
			int x = find(real[i]);
			if(!vis[x]) {
				vis[x] = 1;
				ans++;
			}
		}
		printf("Case #%d: %d\n", cas++, ans);
	}
	return 0;
} 








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值