hdu2473 Junk-Mail Filter

来源:互联网 发布:淘宝保税区要身份证吗 编辑:程序博客网 时间:2024/06/15 03:59

//并查集删除点的操作//给每个点i一个映射id[i],初始id[i]=i//当删除i的时候,将id[i]=cnt++//即使用一个额外的新点代替点i在原树中的位置//每次查询、合并操作途经新点#define _CRT_SECURE_NO_DEPRECATE#include <stdio.h>#include <string.h>#include <stdlib.h>#include <queue>#include <algorithm>#include <vector>#include <stack>#include <math.h>#include <iostream>#include <map>#include <set>#include <functional>using namespace std;#define pow(i) (1<<(i))#define INF (1<<29)#define mem(x) memset(x,0,sizeof(x))#define mem1(x) memset(x,-1,sizeof(x))typedef long long LL;const int maxn=2000010;int pre[maxn],id[maxn];int cnt=0;int N,M;set<int> S;void init(){cnt=N;int i;for(i=0;i<maxn;i++)  //将达到最大值二倍的点全部初始化,在替换点的时候会使用这些点{pre[i]=i;id[i]=i;}}int find(int x){if(pre[x]==x)return x;elsereturn pre[x]=find(pre[x]);}void merge(int a,int b){int pa,pb;a=id[a];//对映射进行操作,被删除的点的子节点pre不改变,从树中被独立出来b=id[b];pa=find(a);pb=find(b);if(pa!=pb)pre[pa]=pb;}int main(){int a,b,ncase=1;char s[5];while(scanf("%d %d",&N,&M)!=EOF){if(N==0&&M==0)break;init();while(M--){scanf("%s",s);if(s[0]=='M'){scanf("%d %d",&a,&b);merge(a,b);}else{scanf("%d",&a);id[a]=cnt++; //此处替换点}}S.clear();for(int i=0;i<N;i++) S.insert(find(id[i]));  //最终计算集合数,查找每个点的映射,即跳过被删除的点。(此时已删除的原来点的pre为被删除前的pre) printf("Case #%d: %d\n",ncase++,S.size());}return 0;}




0 0