2018.09.11【BZOJ1370】团伙(并查集)

传送门

解析:

好裸的并查集。。。

首先如果我们已经得到每个人属于的团伙编号,就只需要查有几个根节点,也就是 fax==x f a x == x 的点。

那么怎么合并?
朋友关系直接合并。

遇到敌人关系的时候,如果对方已经有记录的敌人了,就将自己和对方记录的敌人合并,不然就将自己标记为对方的敌人,因为我敌人的敌人是我的朋友,属于同一个团伙。

代码:

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

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

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

int fa[1001];
int hit[1001];
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);
    fa[i]=j;
}

int n,m;

signed main(){
    n=getint();
    m=getint();
    for(int re i=1;i<=n;++i)fa[i]=i;
    while(m--){
        char op=getalpha();
        int x=getint(),y=getint();
        switch(op){
            case 'E':{
                if(hit[x])merge(hit[x],y);
                else hit[x]=y;
                if(hit[y])merge(hit[y],x);
                else hit[y]=x;
                break;
            }
            case 'F':{
                merge(x,y);
                break;
            } 
        }
    }
    int ans=0; 
    for(int re i=1;i<=n;++i)if(i==fa[i])++ans;
    cout<<ans;
    return 0;
}
    原文作者:犯罪团伙问题
    原文地址: https://blog.csdn.net/zxyoi_dreamer/article/details/82632051
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞