并查集删点操作以前没有做过这种的,mark,好题。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 1000000+100;
int father[maxn];
int ad;
int place[maxn];
int vst[maxn];
int getfather(int fx)
{
int x = fx;
if(x != father[x])
{
father[x] = getfather(father[x]);
}
return father[x];
}
void merge(int a,int b)
{
int fa = getfather(a);
int fb = getfather(b);
if (fa != fb)
{
father[fa] = fb;
}
}
void demerge(int a)
{
father[ad] = ad;
place[a] = ad;
ad++;
}
int main(int argc, char const *argv[])
{
int n,m;
int ncase = 1;
while(scanf("%d%d",&n,&m),m||n)
{
for (int i = 0; i < n; ++i)
{
father[i] = i;
place[i] = i;
}
ad = n;
for(int i = 1; i <= m; ++i)
{
//getchar();
char str[10];
int a,b;
scanf("%s", str);
if (str[0] == 'M')
{
scanf("%d%d",&a, &b);
//需要注意的点,当一个点被换掉以后,现在在树上的是一个假的点,要对这点操作,要找到真的点place[x]
merge(place[a],place[b]);
}
if (str[0] == 'S')
{
scanf("%d", &a);
demerge(a);
}
}
int ans = 0;
memset(vst,0,sizeof(vst));
for (int i = 0; i < n; ++i)
{
int p = getfather(place[i]);
if (!vst[p])
{
ans++;
vst[p] = 1;
}
}
printf("Case #%d: %d\n", ncase++, ans);
}
return 0;
}