题意:给出起点和终点,计算求出最短路径(最短路径即所经过的站点最少的),若最短路径不唯一,则选择其中换乘次数最少的一条线路。

思路:本题虽然也是求最短路径,但是此路径是不带权值的,路径长度即所经过的边数,故可以用DFS来求解,而不是用一般的Dijkstra之类的。相信若只是求最短路径,大多数人都会做,就是从起点start开始深度遍历,遍历到终点end时,与全局变量进行比较、更新。本题的关键是,更新最优路径时需要比较“换乘次数”,如何求解它呢?我是这么思考的——首先,考虑用一个二维数组int mp[maxn][maxn]来存储站点与线路的关系,如mp[6666][8432]=4,表示6666->8432是4号线,但考虑到站点编号的范围最大达到9999,也就是数组得开10000*10000,这显然是无法承受的,故选用unordered_map,令unordered_map<int,unordered_map<int,int>> mp,操作和普通的数组一样。(我发现这个unordered_map真的是非常好用,很多题目都可以用,这里不细说,有兴趣的查看文档进行学习)。那么,怎么算是“换乘”呢?假设前一个站是pre,当前站是curr,下一个站是next,若mp[pre][curr]≠mp[curr][next],说明需要一次换乘,顺序遍历路径path的所有站点,即可求出换乘次数。最后,本题的输出也是比较麻烦,但思路和求换乘次数的方法是一样的。具体请看代码,关键处都有注释。

ps.代码中尽量不要出现中文注释,因为在中文输入法下,若不小心在某一行开头输入了一个空格(难以发现),这会导致编译出错,产生“error: stray '\241' in program”的错误信息。

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <unordered_map>
using namespace std;
;
const int Inf=0x7fffffff;
unordered_map<int,unordered_map<int,int>> mp;//存储两站点间的地铁线,如mp[6666][8432]=4,表示6666->8432是4号线
bool vis[maxn];//在DFS中标记结点是否已经被访问过
vector<int> graph[maxn];//邻接表存储地铁线路图
int k,n,m,s,e,minDistance,minTransfer;//地铁线条数,每条地铁的站点数,查询次数,查询的起点和终点,最短距离,最少换乘数
vector<int> path,tmpPath;//path存放最优路径,tmpPath存放临时路径

int getTransferCnt(vector<int>& path)
{
    ;
    ];
    ;i+<path.size();i++){//注意,这里的判定是i+1<path.size()
        ];
        if(mp[pre][curr]!=mp[curr][next]) changeCnt++;
        pre=curr;//记得更新
    }
    return changeCnt;
}

void dfs(int s)
{
    vis[s]=true;
    tmpPath.push_back(s);
    if(s==e){
        int tmpTransfer=getTransferCnt(tmpPath);
         < minDistance){
            minDistance=tmpPath.size()-;
            minTransfer=tmpTransfer;
            path=tmpPath;
        } == minDistance && tmpTransfer < minTransfer){
            minTransfer=tmpTransfer;
            path=tmpPath;
        }
        return;
    }
    for(auto next:graph[s]){
        if(vis[next] == true) continue;
        dfs(next);
        tmpPath.pop_back();
        vis[next]=false;
    }
}

void printPath(vector<int>& path)
{
    //换乘次数为0时,只需要输出起点和终点,单独输出。这里minTransfer是全局变量,在调用该函数前已经确定
    ){
        ],b=path[path.size()-];//also b=path.back();
        printf(]][path[]],a,b);//注意,这里线路不能是mp[a][b],因为站点a、b不一定是相邻的!
        return;
    }
    ];//表示当前这条线路的起始站
    ],curr,next;
    ;i+<path.size();i++){
        curr=path[i],next=path[i+];
        if(mp[pre][curr]!=mp[curr][next]) {
            printf("Take Line#%d from %04d to %04d.\n",mp[pre][curr],start,curr);
            start=curr;//出现换乘,记得更新起始站
        }
        pre=curr;
    }
    //输出最后一次换乘至终点的线路
    printf(]][path[path.size()-]],start,path[path.size()-]);
}

int main()
{
    //freopen("pat.txt","r",stdin);
    scanf("%d",&k);
    ;i<=k;i++){
        int pre,curr;
        scanf("%d%d",&n,&pre);
        ;j<n;j++){
            scanf("%d",&curr);
            graph[pre].push_back(curr);
            graph[curr].push_back(pre);
            mp[pre][curr]=mp[curr][pre]=i;
            pre=curr;
        }
    }
    scanf("%d",&m);
    while(m--){
        scanf("%d%d",&s,&e);
        //每次查询前千万记得初始化
        memset(vis,false,sizeof(vis));
        path.clear();
        tmpPath.clear();
        minDistance=Inf,minTransfer=Inf;
        dfs(s);
        printf("%d\n",minDistance);
        printPath(path);
    }
    ;
}

1131 Subway Map的更多相关文章

  1. PAT甲级1131. Subway Map

    PAT甲级1131. Subway Map 题意: 在大城市,地铁系统对访客总是看起来很复杂.给你一些感觉,下图显示了北京地铁的地图.现在你应该帮助人们掌握你的电脑技能!鉴于您的用户的起始位置,您的任 ...

  2. PAT甲级——1131 Subway Map (30 分)

    可以转到我的CSDN查看同样的文章https://blog.csdn.net/weixin_44385565/article/details/89003683 1131 Subway Map (30  ...

  3. 1131 Subway Map DFS解法 BFS回溯!

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...

  4. 1131 Subway Map(30 分)

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...

  5. PAT 1131 Subway Map

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...

  6. PAT甲级1131 Subway Map【dfs】【输出方案】

    题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432 题意: 告诉你一个地铁线路图,站点都是 ...

  7. PAT 1131. Subway Map (30)

    最短路. 记录一下到某个点,最后是哪辆车乘到的最短距离.换乘次数以及从哪个位置推过来的,可以开$map$记录一下. #include<map> #include<set> #i ...

  8. PAT_A1131#Subway Map

    Source: PAT A1131 Subway Map (30 分) Description: In the big cities, the subway systems always look s ...

  9. 1131(★、※)Subway Map

    思路:DFS遍历 #include <iostream> #include <map> #include <vector> #include <cstdio& ...

随机推荐

  1. linux的文件

    今日感慨:linux根目录下的文件夹含义 bin的知识,二进制文件,其用途依系统或应用而定 . 也就是说,一般来讲是机器代码,汇编语言编译后的结果,(DOS下汇编语言编译后与.com文件相类似),用d ...

  2. Python Falling back to the 'python' engine because the 'c' engine does not support regex separators

    环境 Anaconda3 Python 3.6, Window 64bit 书籍 O'Reilly出版的Wes McKinney编的<Python for Data Analysis> 警 ...

  3. za2

      程序集?生成后  一个exe,一个dll. 也可以是一个项目. vs 快速生成字段的代码段快捷键,快速生成构造函数,生成普通方法结构的快捷键   ************************* ...

  4. java中的几种实体类对象(PO,VO,DAO,BO,POJO)

    一.PO :(persistant object ),持久对象 可以看成是与数据库中的表相映射的java对象.使用Hibernate来生成PO是不错的选择. 二.VO :(value object) ...

  5. 一些开源搜索引擎实现——倒排使用原始文件,列存储Hbase,KV store如levelDB、mongoDB、redis,以及SQL的,如sqlite或者xxSQL

    本文说明:除开ES,Solr,sphinx系列的其他开源搜索引擎汇总于此.   A search engine based on Node.js and LevelDB A persistent, n ...

  6. zoj-3963 Heap Partition(贪心+二分+树状数组)

    题目链接: Heap Partition Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge A sequence ...

  7. Leetcode 1014. Best Sightseeing Pair

    本题是leetcode121这道题的翻版,做法完全一样,也是扫一遍数组,维护两个值,一个是a[i]+i的最大值,另一个是a[i]+a[j]+i-j的最大值. class Solution: def m ...

  8. Helix Server流媒体服务器架设教程(附Helix Server11.01下载)

    现在D版的远古影视系统很流行,也很实用,但是在这之前,很多人都是用共享,或者是使用Helix Server留媒体来做电影服务器~ 虽然Helix Server流媒体服有点落伍了,不过我相信它还是有用武 ...

  9. (十)js获取日期

    //将日期转换成字符串格式输出 function formatDateToString(){ // 先获取对象日期 var oDate = new Date(); // 从该对象中分别拿出所需要的 年 ...

  10. [转]MFC 调用 printf 输出

    摘自:http://blog.csdn.net/miyunhong/article/details/6704121 #include <io.h> #include <fcntl.h ...