zoukankan      html  css  js  c++  java
  • PAT甲级1131Subway Map

    题目链接

    https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432

    题解

    题目要求

    • 给定起点和目标地,找到最快的路

    • 输入

      • N:正整数,不超过100,地铁线路的数量,索引为[1,n]
      • N条地铁线路:M个站点,站点索引为[0000,9999]
        • 两条地铁线路不会经过同一条边(站到站)
        • 可能存在环,但没有自环
        • 每个站点最多有5条线路经过
      • K:正整数,不超过10,查询的数量
      • K对起点和终点
    • 输出

      对于每个查询,输出最少经过的站数。如果有多个解,输出换线最少的解。

    解题思路

    • 因为存在环,所以在DFS时需要用visit数组表示某个车站是否已经DFS过。其实只要存在可以从多个结点到达某个结点V的情况,就应该设置visit数组标记是否已访问过结点V,如果访问过则不用再访问。
    • 注意输出要按四位输出

    代码

    // Problem: PAT Advanced 1131
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432
    // Tags: 图 DFS
    
    #include <iostream>
    #include <vector>
    using namespace std;
    
    const int MAXN = 10000;
    int line[MAXN][MAXN];
    bool visited[MAXN];
    vector<int> nextStop[MAXN];
    vector<int> tempPath, ansPath;
    int tempTransfer, ansTransfer;
    int n, m, k, start, destination;
    
    void dfs(int stop,int preLine){
        if (visited[stop])
            return ;
        tempPath.push_back(stop);
        visited[stop] = true;
        if (stop == destination){
            if (tempPath.size() < ansPath.size()){
                ansPath = tempPath;
                ansTransfer = tempTransfer;
            }else if(tempPath.size() == ansPath.size() && tempTransfer < ansTransfer){
                ansPath = tempPath;
                ansTransfer = tempTransfer;
            }
        }
        else{
            for (auto it = nextStop[stop].begin(); it != nextStop[stop].end(); it++){
                bool transferFlag = (line[stop][*it] != preLine);
                if (transferFlag)
                    tempTransfer++;
                dfs(*it, line[stop][*it]);
                if (transferFlag)
                    tempTransfer--;
            }
        }
        tempPath.pop_back();
        visited[stop] = false;
    }
    
    int main()
    {
        scanf("%d", &n);
        int u, v;
        for (int i = 1; i <= n; i++){
            scanf("%d%d", &m, &u);
            for (int j = 0; j < m - 1; j++){
                scanf("%d", &v);
                line[u][v] = i;
                line[v][u] = i;
                nextStop[u].push_back(v);
                nextStop[v].push_back(u);
                u = v;
            }
        }
        scanf("%d", &k);
        while (k--){
            scanf("%d%d", &start, &destination);
            tempTransfer = -1;
            ansTransfer = MAXN;
            tempPath.clear();
            ansPath.resize(MAXN);
            dfs(start, 0);
            printf("%d
    ", ansPath.size() - 1);
            int tempStart = start, preLine = line[ansPath[0]][ansPath[1]];
            for(int i = 0; i < ansPath.size() - 1; i++){
                if (preLine != line[ansPath[i]][ansPath[i + 1]]){ // 要换线
                    printf("Take Line#%d from %04d to %04d.
    ", preLine, tempStart, ansPath[i]);
                    tempStart = ansPath[i];
                    preLine = line[ansPath[i]][ansPath[i + 1]];
                }
            }
            printf("Take Line#%d from %04d to %04d.
    ", preLine, tempStart, ansPath.back());
        }
        return 0;
    }
    

    作者:@臭咸鱼

    转载请注明出处:https://www.cnblogs.com/chouxianyu/

    欢迎讨论和交流!


  • 相关阅读:
    10分钟学会在Ubuntu 18.04 LTS上安装NFS服务器和客户端
    脱发、秃头防不胜防?这里有一份给码农的减压指南 [转自机器之心]
    Ubuntu通过apt-get安装指定版本和查询软件源有多少个版本
    ubuntu tree 查看目录结构
    Clion快捷键
    斜杠与反斜杠的记法
    C++ 既有约定
    docker其他参考资料
    标准错误重定向、标准输入重定向
    第一本Docker书读书笔记
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/13771992.html
Copyright © 2011-2022 走看看