Bootstrap

机试题——出城

题目描述

如果将这个城市的路口看作点,两个路口之间的路看作边,那么该城市的道路能够构成一棵由市中心路口向城市四周生长的树,树的叶子节点即是出城口。

今天想要出城办事,但不巧的是,有几个路口堵车了,无法从一个正常的路口前往堵车的路口。假定从一个正常的路口出发,请问能否顺利出城(到达出城口)?如果可以,请找到最省油的路径(经过路口最少的路径),否则请输出“NULL”。

输入描述

  • 第一行:一个整数 ( n ),表示城市有 ( n ) 个路口,路口从 0 开始依次递增,0 固定为根节点,( 1 \leq n < 10000 )。
  • 第二行:一个整数 ( m ),表示接下来有 ( m ) 行,每行是一条道路。
  • 接下来的 ( m ) 行:每行包含两个整数 ( x ) 和 ( y ),表示路口 ( x ) 和路口 ( y ) 之间有一条道路连接。保证是一棵树。
  • 接下来的一行:一个整数 ( d ),表示接下来有 ( d ) 行,每行是一个堵车的路口。
  • 接下来的 ( d ) 行:每行一个整数 ( k ),表示路口 ( k ) 已堵车。

输出描述

  • 如果能够顺利出城,请输出能够到达任意一个出城口的最短路径(通过路口最少),例如从 0 经过 1 到达 2(出城口),那么输出 “0->1->2”。
  • 如果无法出城,输出 “NULL”。
  • 如果存在多条最短路径,请按照节点序号排序输出。

用例输入

样例1

4
3
0 1
0 2
0 3
2
2
3
0->1

说明

  • ( n = 4 ),边为 ([[0,1],[0,2],[0,3]),堵车路口为 ([2, 3])。
  • 可以从 0 到达叶子节点 1,因此输出 “0->1”。

样例2

7
6
0 1
0 3
1 2
3 4
1 5
5 6
1
4
0->1->2

解题思路

  1. 构建图:使用邻接表存储树的结构。
  2. DFS搜索
    • 从根节点开始,递归搜索所有路径。
    • 遇到叶子节点时,记录路径长度和路径。
  3. 路径选择
    • 选择最短路径,如果有多个最短路径,按节点序号排序。
  4. 输出结果:按要求格式输出路径或 “NULL”。

代码

#include <iostream>
#include <vector>
#include <queue>
#include <sstream>
#include <string>
#include <stack>
#include <algorithm>
#include <map>
#include <unordered_map>
using namespace std;

int n, m, d; // 路口数量,边数量,堵车口数量
vector<int> g[10005];
vector<int> dk(10005, 0);
map<int, vector<vector<int>>> res; // 路径长度和路径

void dfs(int root, vector<int>& l) {
    l.push_back(root);
    if (g[root].size() == 0) { // 叶子节点
        res[l.size()].push_back(l);
    } else {
        for (int i = 0; i < g[root].size(); i++) {
            int target = g[root][i];
            if (dk[target] != 1) { // 无障碍
                dfs(g[root][i], l);
            }
        }
    }
    l.pop_back();
    return;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m;
    int st, ed;
    for (int i = 0; i < m; i++) {
        cin >> st >> ed;
        g[st].push_back(ed);
    }
    cin >> d;
    for (int i = 0; i < d; i++) {
        int t;
        cin >> t;
        dk[t] = 1;
    }
    vector<int> temp;
    dfs(0, temp);
    vector<vector<int>> min_res = (*res.begin()).second;
    sort(min_res.begin(), min_res.end());
    if (min_res.size() == 0) {
        cout << "NULL";
        return 0;
    }
    for (int i = 0; i < min_res[0].size(); i++) {
        if (i != min_res[0].size() - 1)
            cout << min_res[0][i] << "->";
        else
            cout << min_res[0][i];
    }
    return 0;
}
;