hdu2473之并查集

思路:每次删除一个点a,并不把a从当前集合删除,而是用一个数组node[a]代表a对应的点,所以每次删除a后,node[a]=++n,即开辟一个新的点作为a对应的点,这样就不会影响a这个集合

http://acm.hdu.edu.cn/showproblem.php?pid=2473

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iomanip>
#define INF 99999999
using namespace std;

const int MAX=100000+10;
int father[MAX+MAX*10],rank[MAX+MAX*10],node[MAX],sum;

void makeset(int num){
	for(int i=0;i<=num;++i){
		father[i]=i;
		rank[i]=1;
	}
}

int findset(int v){
	if(v != father[v])father[v]=findset(father[v]);
	return father[v];
}

void Union(int x,int y){
	int a=findset(x);
	int b=findset(y);
	if(a == b)return;
	if(rank[a]>rank[b]){
		father[b]=a;
		rank[a]+=rank[b];
	}
	else{
		father[a]=b;
		rank[b]+=rank[a];
	}
	--sum;
}

bool Delete(int x){
	int a=findset(x);
	if(rank[a]>1){
		++sum;
		--rank[a];
		return true;
	}
	return false;
} 

int main(){
	int n,m,a,b,num=0;
	char s;
	while(scanf("%d%d",&n,&m),n+m){
		makeset(n+m);
		for(int i=0;i<=n;++i)node[i]=i;
		sum=n;
		for(int i=0;i<m;++i){
			getchar();scanf("%c",&s);
			if(s == 'M'){
				scanf("%d%d",&a,&b);
				Union(node[a],node[b]);
			}
			else{
				scanf("%d",&a);
				if(Delete(node[a]))node[a]=++n;//开辟新点作为a对应的点 
			}
		} 
		printf("Case #%d: %d\n",++num,sum);
	}
	return 0;
} 


 

你可能感兴趣的:(hdu2473之并查集)