Skip to content

Latest commit

 

History

History
77 lines (64 loc) · 3.79 KB

1139. First Contact.md

File metadata and controls

77 lines (64 loc) · 3.79 KB

pat甲级1139. First Contact

题意概述

可以把整个题目描述表示成一个图,每个人都是其中一个结点,两个人如果是朋友则在两个人之间有一条无向边。题目要求的就是给定一个起始结点,一个末尾结点,能不能找到两个结点,使得从起始结点出发经过这两个结点之后到达末尾结点。当然,题目要求比这个稍微复杂,每个节点有男、女两种性别,而且要求经过的两个节点中,第一个节点的性别和起始结点一致,第二个结点的性别和末尾结点一致。

输入输出格式

输入第一行给出两个正整数N和M,分别是总人数和友好关系的数量。接下来M行,每行给一对朋友。在此,一个人用4位数字ID表示。为了区分性别,ID前有负号的代表女孩。接下来一行给出一个正整数K,它是查询的数量。接下来K行,每行给出一对起始节点和末尾节点。

对于每个查询,首先在一行中打印他们可以找到的不同对朋友的数量,然后在每行中打印一对朋友的ID。如果恋人A和B的性别相反,则必须首先打印与A性别相同的A的朋友,然后打印与B性别相同的B的朋友。确保每个人只有一个性别。朋友必须按照第一个ID的非降序顺序打印,如果第一个ID相同,则按第二个ID的升序打印。

数据规模

$$1<N<=300,K<=100$$

算法设计

由于只要求首尾结点之间有两个结点,且结点总数最多才300个,无需DFS或BFS,可以直接采取暴力枚举的方法,在枚举过程中,注意保证第一个节点和首结点性别相同,第二个节点和末尾结点性别相同,此外要避免过早达到头结点或返回首节点的情况出现。具体实现可见代码。

注意点

  1. 有一个大坑,题目按给定的4位数字前有无-号作为区别男女的标志,有一个测试点包含了-0000这样的数据,如果用long long读入,是不会认为它是一个负数的,于是程序自然把其代表的人视作了女性,导致了错误。所以为了保证正确,最好用string读入,以确保前面的-号不会丢失。
  2. 输出结点值时要按%04d的形式输出,以保证输出数字有4位,不足在高位补0。
  3. 形成的图为无向图,边为无向边。
  4. 搜索过程中避免过早达到头结点或返回首节点的情况出现,即保证搜索的两个结点既不等于首节点,也不等于尾结点

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    unordered_map<gg, bool> boys;
    unordered_map<gg, vector<gg>> graph;
    gg ni, mi, ki, s, e;
    cin >> ni >> mi;
    for (gg i = 0; i < mi; ++i) {
        string a, b;
        cin >> a >> b;
        gg ag = abs(stoll(a)), bg = abs(stoll(b));
        graph[ag].push_back(bg);
        graph[bg].push_back(ag);
        boys[ag] = a[0] != '-';
        boys[bg] = b[0] != '-';
    }
    cin >> ki;
    while (ki--) {
        cin >> s >> e;
        s = abs(s), e = abs(e);
        vector<array<gg, 2>> ans;
        for (gg i : graph[s]) {
            if (i != e and i != s and boys[i] == boys[s]) {
                for (gg j : graph[i]) {
                    if (j != e and j != s and boys[j] == boys[e]) {
                        for (gg k : graph[j]) {
                            if (k == e) {
                                ans.push_back({i, j});
                            }
                        }
                    }
                }
            }
        }
        cout << ans.size() << "\n";
        sort(ans.begin(), ans.end());
        for (auto& i : ans) {
            cout << setfill('0') << setw(4) << i[0] << " " << setw(4) << i[1]
                 << "\n";
        }
    }
    return 0;
}