2018.09.15【HDU2437】Junk-Mail Filter (并查集)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82714210

传送门


解析:

用一个 p o s 数组表示当前节点在并查集中的对应节点编号。

删除的时候直接更改节点 p o s 值就行了。

还有。
为什么 r a n k 是关键字啊!!!
为什么 H D U 下标强制从0开始啊???


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define rank Rank

inline
ll getint(){
    re ll num=0;
    re char c;
    while(!isdigit(c=gc()));
    while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
    return num;
}

inline
void outint(ll a){
    static char ch[23];
    if(a==0)pc('0');
    while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
    while(ch[0])pc(ch[ch[0]--]);
}

inline char getalpha(){
    re char c;
    while(!isalpha(c=gc()));
    return c;
}

int n,m;
int pos[100002],tot;
int fa[1100002];
int rank[1100002];
bool vis[1100002];

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

inline
void merge(int i,int j){
    i=getfa(i),j=getfa(j);
    if(i==j)return ;
    if(rank[i]>rank[j])swap(i,j);
    fa[j]=i;
    if(rank[i]==rank[j])++rank[i];
}

int tt;
signed main(){
    while(n=getint(),m=getint(),n+m){
        ++tt;
        memset(rank,0,sizeof rank);
        memset(vis,0,sizeof vis);
        for(int re i=0;i<n;++i)fa[i]=i,pos[i]=i;
        tot=n-1;
        while(m--){
            char op=getalpha();
            switch(op){
                case 'M':{
                    int x=getint(),y=getint();
                    merge(pos[x],pos[y]);
                    break;
                }
                case 'S':{
                    int x=getint();
                    fa[pos[x]=++tot]=tot;
                    break;
                }
            }
        }
        int ans=0;
        for(int re i=0;i<n;++i)if(!vis[getfa(pos[i])])++ans,vis[getfa(pos[i])]=true;
        printf("Case #%d: %d\n",tt,ans); 
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82714210