峰会

146 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

题目信息描述

峰会是国家元首或政府首脑的会议。

为峰会安排休息区可不是一件简单的工作。

一共有 N 个首脑参加峰会,编号 1∼N。

这些首脑之间存在 M 对两两之间的直接朋友关系。

在划分区域时,我们希望被安排在同一休息区域的首脑们满足,任意两人之间都是直接朋友关系。

现在,给定 K 个关于划分休息区域的安排,请你依次判断每个安排是否合理。

输入格式

第一行包含两个整数 N 和 M。

接下来 M 行,每行包含两个整数 a,b,表示首脑 a 和首脑 b 之间存在直接朋友关系。

再一行包含整数 K。

接下来 K 行,每行描述一个区域安排,首先包含一个整数 L,表示该安排打算将 L 个首脑安排在同一区域休息,然后包含 LL 个整数,表示这些首脑的编号。

输出格式

共 KK 行,第 ii 行输出对第 ii 个安排的判断,具体格式为

  • 如果安排满足其中的任意两人之间都是直接朋友关系并且不存在额外的人与被安排的所有人都是直接朋友关系(即无法安排更多的人在这一区域休息),则输出 Area X is OK.
  • 如果安排满足其中的任意两人之间都是直接朋友关系并且存在额外的人与被安排的所有人都是直接朋友关系(即可以安排更多的人在这一区域休息),则输出 Area X may invite more people, such as H.,其中 H 是额外可被安排的人的编号(如果不唯一,则输出最小的那个)。
  • 如果安排无法满足其中的任意两人之间都是直接朋友关系,则输出 Area X needs help.

X 表示组别编号,从 11 到 KK。

数据范围

1≤N≤2001≤N≤200, 1≤M≤N(N−1)21≤M≤N(N−1)2, 1≤a,b≤N1≤a,b≤N, a≠ba≠b, 1≤K≤1001≤K≤100, 1≤L≤N1≤L≤N, 同一对直接朋友关系不会在输入中重复出现。

输入样例:

8 10
5 6
7 8
6 4
3 6
4 5
2 3
8 2
2 7
5 3
3 4
6
4 5 4 3 6
3 2 8 7
2 2 3
1 1
2 4 6
3 3 2 1

输出样例:

Area 1 is OK.
Area 2 is OK.
Area 3 is OK.
Area 4 is OK.
Area 5 may invite more people, such as 3.
Area 6 needs help.

思路

本题乍一眼一看是并查集的题目,但题目说要直接朋友,并不用查间接朋友,所以我们可以看成一个图论的问题。只需要建一个无向图即可,即若a与b是朋友则ga=gb=1。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>using namespace std;
​
const int N = 210, M = 110;
​
int n, m;
int g[N][N];
int a[N];
​
int main()
{
    cin >> n >> m;
​
    /*构建无向图*/
    while (m -- ) 
    {
        int a, b;
        cin >> a >> b;
        g[a][b] = g[b][a] = 1;
    }
​
    int T;
    cin >> T;
​
    /*T次询问*/
    for (int t = 1; t <= T; t ++ ) 
    {
        int k;
        cin >> k;
        set<int> s;
        for (int i = 0; i < k; i ++ ) cin >> a[i], s.insert(a[i]);
        /*看一下同一房间宾客是否都相互认识*/
        bool flag = false;
        for (int i = 0; i < k; i ++ ) 
            for (int j = i + 1; j < k; j ++ )
                if (!g[a[i]][a[j]])
                {
                    flag = true;
                    break;
                }
​
        /*若都相互认识,则看一下是否还能安插一个宾客,还能使得房间内的宾客相互认识*/
        bool flag_1 = false;
        int tt = 0;
        if (!flag)
        {
            for (int i = 1; i <= n; i ++ ) 
                if (!s.count(i))
                {
                    bool flag_2 = false;
                    for (int j = 0; j < k; j ++ ) 
                        if (!g[a[j]][i])
                        {
                            flag_2 = true;
                            break;
                        }
                    if (!flag_2)
                    {
                        flag_1 = true;
                        tt = i;
                        break;
                    }
                }
        }
​
        if (flag)
            printf("Area %d needs help.\n", t);
        else if (!flag && !flag_1)
            printf("Area %d is OK.\n", t);
        else 
            printf("Area %d may invite more people, such as %d.\n", t, tt);
    }
    return 0;
}