BZOJ 1370: [Baltic2003]Gang团伙(并查集)

Description

在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1、 我朋友的朋友是我的朋友; 2、 我敌人的敌人是我的朋友; 所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?
Input

第1行为n和m,N小于1000,M小于5000; 以下m行,每行为p x y,p的值为0或1,p为0时,表示x和y是朋友,p为1时,表示x和y是敌人。
Output

一个整数,表示这n个人最多可能有几个团伙。


题解:
将每一个人拆成两个点,一种是朋友i,一种是敌人i+n

如果x,y两个人是朋友,直接连上即可

如果x,y两个人是敌人,就都将自己和对方的敌对点连上就能表示敌人的敌人是朋友啦


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define LL long long
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 2000+10;
const int MOD = 1000000007;
const int INF = 0x3f3f3f3f;
int pre[MAXN],vis[MAXN]; char op[10];
int Find(int x){ return pre[x]==x ? pre[x]:pre[x]=Find(pre[x]); }
signed main(){
#ifndef ONLINE_JUDGE
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
    int n,Q,res=0; scanf("%d%d",&n,&Q);
    for(int i=1;i<=2*n;i++) pre[i]=i;
    while(Q--){
        int x,y,xx,yy; scanf("%s%d%d",op,&x,&y);
        if(op[0]=='F'){
            xx=Find(x),yy=Find(y);
            if(xx!=yy) pre[yy]=xx;
        }else if(op[0]=='E'){
            xx=Find(x),yy=Find(y+n);
            if(xx!=yy) pre[xx]=yy;
            xx=Find(x+n),yy=Find(y);
            if(xx!=yy) pre[yy]=xx;
        }
    }
    for(int i=1;i<=n;i++) if(!vis[Find(i)]) res++,vis[Find(i)]=1;
    printf("%d\n",res);
    return 0;
}

发布了152 篇原创文章 · 获赞 1 · 访问量 2699

猜你喜欢

转载自blog.csdn.net/qq_43544481/article/details/103839269