并查集(删点)

传送门

有 n 棵树,编号 0 到 n - 1 , 本来以为它们是 n 种不同的树,但是我们陆陆续续的得到了 m 条消息,发现之前统计错了。

消息有如下两种格式:

  • ”M a b" ,编号 a 和 编号 b 的树划分为一种树 ;
  • "S a", 将编号为 a 的树从它所属的种类里拿出来,成为一个新的种类;

请问最终有多少种树 ?

Input

输入文件中有多个测试用例。

每个测试用例第一行是两个整数 n 和 m(1 ≤ n ≤ 1e5,1 ≤ M ≤ 1e6),随后是 m 行,每行是上述两种格式之一。

n = 0 和 m = 0 的时候结束。

Output

对于每个测试用例,打印一个整数 —— 树的种类。具体格式参照样例。

Sample Input

5 6
M 0 1
M 1 2
M 1 3
S 1
M 1 2
S 3

3 1
M 1 2

0 0

Sample Output

Case #1: 3
Case #2: 2

主要是删除的时候肯定不能像以前一样删除

合并操作就是找到找到两个节点的父亲,修改父亲,如果删除就是将该点的父亲重新设置成自己,但是这是不行的,比如1,2,3的父亲都是1,现在删除1,1的父亲还是1,2,3也是1,集合还是1个,正确的应该是2个。

那删除节点的父亲不设成自己给新申请一个节点当做父亲,比如1,2,3的父亲都是1,在一个集合,现在删除1,申请了4当做1的父亲,2,3父亲都是1,然后Find(2)找2的父亲 2的父亲是1,但是1的父亲是4,所以给2的父亲更新成了4,3同理,所以还不行。

正确的方法是每一个点都设立一个虚拟父亲比如1,2,3的父亲分别是4,5,6,现在合并1,2,3都在一个集合,那他们的父亲都是4,现在删除1,那就给1重新申请一个节点7

现在2,3的父亲是4,1的父亲是7,删除成功。


#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e6+100;
int pre[maxn];
int vis[maxn];
int n,m;
int kase=0;
int id; 
int find(int x){
    if(pre[x]!=x){
        pre[x]=find(pre[x]);
    }
    return pre[x];
} 
void marge(int x,int y){
    int t1=find(x);
    int t2=find(y);
    if(t1!=t2){
        pre[t1]=t2;
    }
}
void del(int x){
    pre[x]=id++;
}
void inint(){
    for(int i=0;i<n;i++){
        pre[i]=i+n; 
        vis[i]=0;
    }
    for(int i=n;i<=n+n+m;i++){//最多m次操作 
        pre[i]=i;
        vis[i]=0;
    } 
    id=n+n;
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        if(n+m==0){
            break;
        }
        inint();
        int x,y;
        char a[maxn];
        for(int i=1;i<=m;i++){
            scanf("%s",a);
            if(a[0]=='M'){
                scanf("%d%d",&x,&y);
                marge(x,y);
            }
            else{
                scanf("%d",&x);
                del(x);
            }
        }
        int ans=0;
        for(int i=0;i<n;i++){
            int t=find(i);
            if(!vis[t]){
                ans++;
                vis[t]=1;
            }
        }
        printf("Case #%d: %d\n",++kase,ans); 
    } 
} 

 

posted @ 2020-11-12 00:00  哎呦哎(iui)  阅读(135)  评论(0编辑  收藏  举报