其他分享
首页 > 其他分享> > P1892 [BOI2003]团伙

P1892 [BOI2003]团伙

作者:互联网

题目描述

现在有 n 个人,他们之间有两种关系:朋友和敌人。我们知道:

现在要对这些人进行组团。两个人在一个团体内当且仅当这两个人是朋友。请求出这些人中最多可能有的团体数。

输入格式

第一行输入一个整数 n 代表人数。

第二行输入一个整数 m 表示接下来要列出 m 个关系。

接下来 m 行,每行一个字符 opt 和两个整数 p,q,分别代表关系(朋友或敌人),有关系的两个人之中的第一个人和第二个人。其中 opt 有两种可能:

输出格式

一行一个整数代表最多的团体数。

说明/提示

对于 100\% 的数据,2≤n≤1000,1≤m≤5000,1≤p,q≤n。

输入输出样例

输入 #1
6
4
E 1 4
F 3 5
F 4 6
E 1 2
输出 #1
3


 

分析:

利用并查集,用一个二维数组enemy[][]表示两个人之间的关系(当数组值为true时表示两人关系为敌人)如果两个人关系为朋友,就将两人合并为一组,选其中一人为另一人的根节点便于计算最终组数。其中要判断敌人的敌人为朋友,记为一组。

代码

#include <iostream>

using namespace std;

int team[1050];

int root(int n) //找n的根节点
{
    if (team[n]!=n) team[n]=root(team[n]);
    return team[n];
}
void hebing(int i,int j) //将i和j合并
{
    int r1,r2;
    r1=root(i);
    r2=root(j);
    if (r1!=r2) team[r2]=r1;
}

int main()
{
    int n,m,p,q,counter=0;
    char opt;
    bool enemy[1050][1050];
    cin>>n>>m;
    for (int i=1;i<=n;i++) team[i]=i; //初始化将每个人的根节点设为自己
    for (int i=1;i<=m;i++)
    {
        cin>>opt>>p>>q;
        if (opt=='F') hebing(p,q); //为朋友,则合并
        if (opt=='E')
        {
            enemy[p][q]=true;
            enemy[q][p]=true; //p和q互为敌人
            for (int i=1;i<=n;i++)
            {
                if (enemy[p][i]) hebing(q,i); //p和q、p和i都是敌人,则q和i是朋友,合并
                if (enemy[q][i]) hebing(p,i);
            }
        }
    }
    for (int i=1;i<=n;i++)
    {
        if (team[i]==i) counter++;
    }
    cout<<counter;
    return 0;
}

 

标签:opt,enemy,int,P1892,朋友,team,BOI2003,敌人,团伙
来源: https://www.cnblogs.com/branthx/p/16412154.html