团体天梯练习 L2-010 排座位

发布时间 2023-04-17 13:07:14作者: Amαdeus

L2-010 排座位

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

输入格式:

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

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

输出格式:

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

输入样例:

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

输出样例:

No problem
OK
OK but...
No way


解题思路

题中说需要判断两个人是否存在共同的朋友,对于这一点,只需要用并查集就可以了;至于敌对关系,注意题中说的“但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的”,这句话表明我们无需使用扩展并查集来确定两者的首领是否存在敌对关系,只需要用一个数组来记录两者是否存在敌对关系即可。我一开始自己写的时候没看到这句话,上来就扩展并查集,写了半天才发现不太对...

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, int> psi;
typedef __int128 int128;
#define PI acos(-1.0)
#define x first
#define y second
//int dx[4] = {1, -1, 0, 0};
//int dy[4] = {0, 0, 1, -1};
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;

const int N = 110;
int fa[N], n, m, q;
bool g[N][N];   //存储敌对关系

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

void Union(int u, int v){
    int fu = find(u), fv = find(v);
    if(fu == fv) return;
    fa[fv] = fu;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    cin >> n >> m >> q;
    for(int i = 1; i <= n; i ++ ) fa[i] = i;
    while(m -- ){
        int u, v, c; cin >> u >> v >> c;
        if(c == 1) Union(u, v);
        else g[u][v] = g[v][u] = true;   //只需要存储单纯的敌对关系 无序扩展并查集
    }

    while(q -- ){
        int u, v; cin >> u >> v;
        int fu = find(u), fv = find(v);
        if(fu == fv){
            if(g[u][v]) cout << "OK but..." << endl;  //有共同朋友但敌对
            else cout << "No problem" << endl;        //有共同朋友且不敌对
        }else{
            if(g[u][v]) cout << "No way" << endl;     //无共同朋友但敌对
            else cout << "OK" << endl;                //无共同朋友 不敌对
        } 
    }

    return 0;
}