bzoj1370 团伙 【并查集】

题目描述

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

输入格式

第 1 行为 n 和 m ,其中 1

输出格式

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

样例数据 1

输入
6 4
1 1 4
0 3 5
0 4 6
1 1 2

输出
3

备注

【样例说明】
{1},{2,4, 6},{3,5} 共 3 个团伙。

解题报告:

并查集实现,算法如下:
1、如果 x 和 y 是朋友,则把 x 和 y 合并为一个团伙。
2、如果 x 和 y 是敌人,则继续判断:
(1)如果 x 的敌人 z 存在,在把 z 和 y 合并为一个团伙。因为敌人的敌人是朋友。
(2)如果 y 的敌人 z 存在,在把 z 和 x 合并为一个团伙。因为敌人的敌人是朋友。
3、统计团伙数量即可(即fa[x]=x的个数)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=1005;
int n,m,ans,fa[N],en[N][N];

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

void merge(int x,int y)
{
    int fx=getfa(x),fy=getfa(y);
    if(fx!=fy)fa[fy]=fx;
}

int main()
{
    //freopen("lx.in","r",stdin);
    int op,x,y;
    n=getint(),m=getint();
    for(int i=1;i<=n;i++)fa[i]=i;
    while(m--)
    {
        op=getint(),x=getint(),y=getint();
        if(op==0)merge(x,y);
        else
        {
            for(int z=1;z<=n;z++)
                if(en[x][z])merge(y,z);
            for(int z=1;z<=n;z++)
                if(en[y][z])merge(x,z);
            en[x][y]=en[y][x]=1;
        }
    }
    for(int i=1;i<=n;i++)
        if(fa[i]==i)ans++;
    cout<<ans;
    return 0;
}
    原文作者:犯罪团伙问题
    原文地址: https://blog.csdn.net/cdsszjj/article/details/77915968
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞