http://acm.hust.edu.cn/vjudge/contest/view.action?cid=34236#problem/G
题意:给你n个数,和m步操作,其中操作为M和S, M a b代表a和b处于同一集合中,S a代表将a及其集合都删除,最后统计集合的个数
解析:其余基础并查集,但是用到了并查集的删除操作;
并查集的删除操作,可以理解为开辟双重范围的数组,初始化时将其父节点赋值给同一个值,当删除某一结点时,为了不影响和该点位于同一集合中的点,所以直接将需要删除的点的父节点,赋值为某一新点,这里采用的是大于双重范围数组的基础上递增。
// g.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 10000005;
int fa[ maxn ], temp;
bool flag[ maxn ];
void Start( int n, int m ){
for( int i = 0; i < n; ++i ){
fa[ i ] = n + i;
}
for( int i = n; i < 2 * n + m; ++i ){
fa[ i ] = i;
}
}
int find( int x ){
if( x == fa[ x ] )
return x;
int temp = find( fa[ x ] );
return fa[ x ] = temp;
}
void Union( int a, int b ){
int x = find( a );
int y = find( b );
if( x != y ){
fa[ y ] = x;
}
}
void Delete( int x ){
fa[ x ] = temp++;
}
//int _tmain(int argc, _TCHAR* argv[])
int main()
{
int n, m, a, b, ans, Case = 1;
char ch;
while( cin >> n >> m ){
if( !n && !m )
break;
Start( n, m );
temp = n + n;
while( m-- ){
cin >> ch;
if( ch == 'M' ){
cin >> a >> b;
Union( a, b );
}
else{
cin >> a;
Delete( a );
}
}
memset( flag, false, sizeof( flag ) );
ans = 0;
for( int i = 0; i < n; ++i ){
int x = find( i );
if( !flag[ x ] ){
ans++;
flag[ x ] = true;
}
}
cout << "Case #" << Case++ << ": ";
cout << ans << endl;
}
return 0;
}