• 布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。

    输入格式:

    输入第一行给出3个正整数:N(≤100),即前来参宴的宾客总人数,则这些人从1到N编号;M为已知两两宾客之间的关系数;K为查询的条数。随后M行,每行给出一对宾客之间的关系,格式为:宾客1 宾客2 关系,其中关系为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K行,每行给出一对需要查询的宾客编号。

    这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。

    输出格式:

    对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出No problem;如果他们之间并不是朋友,但也不敌对,则输出OK;如果他们之间有敌对,然而也有共同的朋友,则输出OK but...;如果他们之间只有敌对关系,则输出No way

    输入样例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    7 8 4
    5 6 1
    2 7 -1
    1 3 1
    3 4 1
    6 7 -1
    1 2 1
    1 4 1
    2 3 -1
    3 4
    5 7
    2 3
    7 2

    输出样例:

    1
    2
    3
    4
    No problem
    OK
    OK but...
    No way

思路:

  • 根据题意中只有单纯直接的敌对关系才是绝对不能同席的,可建立并查集,以朋友关系为因子进行合并,敌对关系不合并

    通过并查集判断是否有共同朋友

    输出关系如下:

    1
    2
    3
    4
    graph LR
    A(No problem) -->|没有共同朋友&&不直接敌对| B(OK)
    B -->|有共同朋友&&不直接敌对| C(OK but...)
    C -->|直接敌对| D(No way)

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>

using namespace std;
constexpr int MAX_SIZE = 102;

int f[MAX_SIZE];//朋友并查集

int my_query(const int &i) {
return f[i] = f[i] == i ? i : my_query(f[i]);
}

void my_merge(const int &l, const int &r) {
int a = my_query(l);
int b = my_query(r);
f[b] = a;
}

int main() {
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++) {//初始化并查集
f[i] = i;
}
bool f_map[MAX_SIZE][MAX_SIZE] {false};//是否直接朋友
bool d_map[MAX_SIZE][MAX_SIZE] {false}; //是否直接敌对
for (int i = 1; i <= m; i++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if (c == 1) {
f_map[a][b] = true;
f_map[b][a] = true;
my_merge(a, b);
} else {
d_map[a][b] = true;
d_map[b][a] = true;
}
}
for (int i = 1; i <= n; i++) {//并查集收束
f[i] = my_query(f[i]);
}
for (int i = 1; i <= k; i++) {
int a, b;
scanf("%d %d", &a, &b);
if (f_map[a][b]) {//直接朋友
printf("No problem\n");
} else if (f[a] != f[b] && !d_map[a][b]) {//既不是朋友,也不敌对
printf("OK\n");
} else if (f[a] == f[b] && d_map[a][b]) {//有共同朋友,但是直接敌对
printf("OK but...\n");
} else {//无共同朋友,且直接敌对
printf("No way\n");
}
}
return 0;
}