题目链接:SPOJ - JMFILTER - Junk-Mail Filter
题意很明显,就是维护一个带删除的并查集。
如果跟以往一样 f[x]=x,的初始化,那么如果删除的点是根节点就很麻烦,所以我们对每个点建立一个新的父亲节点,每次删除的时候,改变父亲节点即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e6+10;
int n,m,res,ts;
int f[N],id[N],vis[N],cnt; char op[5];
inline int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void init(){
memset(vis,0,sizeof vis); res=0; cnt=n;
for(int i=1;i<=n;i++) f[i]=id[i]=i;
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
inline void merge(int x,int y){f[find(id[x])]=find(id[y]);}
inline void del(int x){id[x]=++cnt; f[cnt]=cnt;}
inline void solve(){
init();
for(int i=1,x,y;i<=m;i++){
scanf("%s",op);
if(op[0]=='M') x=read()+1,y=read()+1,merge(x,y);
else x=read()+1,del(x);
}
for(int i=1,x;i<=n;i++) if(!vis[x=find(id[i])]) res++,vis[x]=1;
printf("Case #%d: %d\n",++ts,res);
}
signed main(){
while(cin>>n>>m,n+m) solve();
return 0;
}