[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个人最多可能有几个团伙。

Sample Input
6
4
E 1 4
F 3 5
F 4 6
E 1 2

Sample Output
3

HINT
{1},{2,4,6},{3,5}

Source

题解
并查集真水。
如果只有第一个条件,那么这道题就非常水,可以说是裸题了。但是,第二个条件就比较麻烦了。为了解决这个问题,可以对每个人(记为x)构造一个“宿敌”x+n。如果读入的两个人x和y是朋友,就将x和y放入一个集合。如果读入的两个人x和y是敌人,就将x和y+n、x+n和y连起来(因为敌人的敌人是朋友)。最后枚举1~n,寻找他们属于多少个集合即可。
样例图:(这里用横线代表是朋友,用带双向箭头的横线代表是敌人)
这是样例
处理后的样例图:(可以看出,画圈的点分别属于三个集合)
这是对于样例的处理

标程

#include <cstdio>
#include <algorithm>

const int maxn=1000;

int fa[maxn*2+10],a[maxn+10];
int n,m,i,j,x,y,ans;
char c;

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

int merge(int x,int y)
{
    x=find(x);
    y=find(y);
    if (x!=y)
    {
        fa[x]=y;
    }
    return 0;
}

int main()
{
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++)
    {
        getchar();
        scanf("%c%d%d",&c,&x,&y);
        if (c=='F')
        {
            merge(x,y);//将x和y合并 
        }
        if (c=='E')
        {
            merge(x,y+n);//将x和y+n合并 
            merge(x+n,y);//将x+n和y合并 
        }
    }
    for (i=1;i<=n;i++)
    {
        a[i]=find(i);//寻找属于哪一个并查集 
    }
    std::sort(a+1,a+n+1);
    ans=1;
    for (i=2;i<=n;i++)
    {
        if (a[i]!=a[i-1])
        {
            ans++;//计算属于多少个并查集 
        }
    }
    printf("%d\n",ans);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值