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
Sample Output
带删除操作的并查集。。
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;
}
原文地址:http://blog.csdn.net/u014355480/article/details/43539171