hdu 2473 Junk-Mail Filter(并查集)

题意:

N个邮件需要鉴别。

两种操作:

1. M X Y:X和Y是同一种邮件

2.S X:X被误判(意味着X要被它从属的那个集合“踢出去"而所有其它的邮件的关系保持不变)

问最后总共有几种邮件。

思路:

用并查集可以实现邮件的“合并”。但是要把单独的X“踢出去”,然后又要保证其它的关系不变。

弄个双层结构,第一层结构是用来描述邮件之前的关系的。第二层结构是用来指向第一层的结点。

第一层是fa,第二层是vfa。当X被“踢出去”时,只要在第一层中新加一个点,然后vfa[x]指向这个新结点即可。

既保留了原来的邮件之前的关系,又顺利地把X“踢出去”了。

代码:

int n,m;
int fa[1200005];
int vfa[100005];


int findFa(int x){
    return fa[x]==x?fa[x]:fa[x]=findFa(fa[x]);
}



int main(){

    int T=0;
    while(scanf("%d%d",&n,&m),n||m){
        rep(i,1,n){
            fa[i]=i;
            vfa[i]=i;
        }
        int cn=n;

        while(m--){
            char ope[5];
            scanf("%s",ope);
            if(ope[0]=='M'){
                int a,b;
                scanf("%d%d",&a,&b);
                int fx=findFa(vfa[a+1]);
                int fy=findFa(vfa[b+1]);
                if(fx!=fy){
                    fa[fx]=fy;
                }
            }else{
                int x;
                scanf("%d",&x);
                vfa[x+1]=++cn;
                fa[cn]=cn;
            }
        }
        map<int,int> mp;
        mp.clear();

        int ans=0;

        rep(i,1,n){
            int t=findFa(vfa[i]);
            if(mp[t]==0){
                mp[t]=1;
                ++ans;
            }
        }
        printf("Case #%d: %d
",++T,ans);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/fish7/p/4332142.html