【bzoj1370】[Baltic2003]Gang团伙 并查集

题目描述

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

输入

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

输出

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

样例输入

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

样例输出

3


题解

并查集

输入描述有误,以下m行第一个是字母,F表示friend,E表示enemy。

如果x、y是朋友,则合并x和y;

如果x、y是敌人,则合并x、y+n和x+n、y。

这样能保证敌人的敌人是朋友,满足题中条件。

然后统计有多少个f[i]就可以。

#include <cstdio>
int f[2010] , vis[2010];
char str[5];
int find(int x)
{
    return x == f[x] ? x : f[x] = find(f[x]);
}
void merge(int x , int y)
{
    int tx = find(x) , ty = find(y);
    f[tx] = ty;
}
int main()
{
    int n , m , i , x , y , ans = 0;
    scanf("%d%d" , &n , &m);
    for(i = 1 ; i <= 2 * n ; i ++ )
        f[i] = i;
    while(m -- )
    {
        scanf("%s%d%d" , str , &x , &y);
        if(str[0] == 'F')
            merge(x , y);
        else
            merge(x , y + n) , merge(x + n , y);
    }
    for(i = 1 ; i <= n ; i ++ )
        if(!vis[find(i)])
            vis[f[i]] = 1 , ans ++ ;
    printf("%d\n" , ans);
    return 0;
}
posted @ 2017-02-16 13:39  GXZlegend  阅读(720)  评论(0编辑  收藏  举报