BZOJ 1370: [Baltic2003]Gang团伙(luogu 1892)(种类并查集)

题面:

  bzoj题面有误,还是看luogu的吧

  https://www.luogu.org/problemnew/show/P1892

题解:

  种类并查集。。

  因为有敌人的敌人是朋友这个条件,所以需要一个中转点。。

  因此,将每个点拆成两个点,一个是朋友点,另一个是敌人点。当读到A与B是朋友时,就将A与B所对应的朋友点并集;当读到两个点是敌人的时候,就将A点所对应的敌人点与B所对应的朋友点并集,将A所对应的朋友点和B所对应的敌人点并集。

  P.S.当读到A与B点是朋友时,不能将A与B点所对应的敌人结点并集,因为题目并没有说朋友的敌人是敌人。

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn=3010;
int fa[maxn],n,m,x,y,vis[maxn],ans;
char ch[3];

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

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=2*n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        scanf("%s%d%d",ch,&x,&y);
        if(ch[0]=='F'){
            int fx=ffa(x),fy=ffa(y);
            if(fx!=fy) fa[fy]=fx;
        }
        else{
            int fx=ffa(x),fy=ffa(y);
            int fxx=ffa(x+n),fyy=ffa(y+n);
            if(fx!=fyy) fa[fyy]=fx;
            if(fxx!=fy) fa[fxx]=fy;    
        }
    }
    for(int i=1;i<=n;i++)
        if(!vis[ffa(i)])
            ans++,vis[ffa(i)]=1;
    printf("%d",ans);
    return 0;    
}

 

posted @ 2018-04-09 17:35  Jack_the_Ripper  阅读(150)  评论(0编辑  收藏  举报