【洛谷】P1892 团伙(并查集)+ 求助

题目描述

1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:

我朋友的朋友是我的朋友;

我敌人的敌人也是我的朋友。

两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。

输入输出格式

输入格式:

 

输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。

 

输出格式:

 

输出文件gangs.out只有一行,表示最大可能的团伙数。

 

输入输出样例

输入样例#1: 
6
4
E 1 4
F 3 5
F 4 6
E 1 2
输出样例#1: 
3
--------------------------------------------------------
析:维护这种有传递性的父子关系,当然用并查集啦!

  求助问一个问题,为什么两人(a , b)是朋友时不用unite(a+n,b+n),但2024食物链却要unite(a,b) unite(a+n,b+n) unite(a+n*2,b+n*2),知道的能不能在下面评论一下,谢谢啦。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=2050;
int pa[maxn],table[maxn],rank[maxn],n;//num是以i为根的团伙数 
void init()
{
    for(int i=0;i<maxn;i++)
    {
        pa[i]=i;
    }
}
int find(int x)
{
    if(pa[x]==x) return x;
    else return pa[x]=find(pa[x]);
}
void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y) return;
    if(rank[x]<rank[y])
        pa[x]=y;
    else
    {
        pa[y]=x;
        if(rank[x]==rank[y]) rank[x]++;
    }
    return;
}
int main()
{
    int m,maxnum=0;
    char s[10];
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%s%d%d",s,&a,&b);
        if(s[0]=='F')
        {
            unite(a,b);
        //    unite(a+n,b+n);
        }
        else
        {
            unite(a,b+n);
            unite(a+n,b);
        }
    }
    for(int i=1;i<=n;i++)
        table[find(i)]=1;//有多少团伙
    for(int i=1;i<=2*n;i++)
        if(table[i]==1) maxnum++;
    printf("%d",maxnum);
    return 0;
} 

 

posted @ 2017-10-23 18:04  noble_(noblex)  阅读(352)  评论(0编辑  收藏  举报
/* */