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

思路:本题虽然也是求最短路径,但是此路径是不带权值的,路径长度即所经过的边数,故可以用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”的错误信息。

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <vector>
  4. #include <unordered_map>
  5. using namespace std;
  6. ;
  7. const int Inf=0x7fffffff;
  8. unordered_map<int,unordered_map<int,int>> mp;//存储两站点间的地铁线,如mp[6666][8432]=4,表示6666->8432是4号线
  9. bool vis[maxn];//在DFS中标记结点是否已经被访问过
  10. vector<int> graph[maxn];//邻接表存储地铁线路图
  11. int k,n,m,s,e,minDistance,minTransfer;//地铁线条数,每条地铁的站点数,查询次数,查询的起点和终点,最短距离,最少换乘数
  12. vector<int> path,tmpPath;//path存放最优路径,tmpPath存放临时路径
  13.  
  14. int getTransferCnt(vector<int>& path)
  15. {
  16. ;
  17. ];
  18. ;i+<path.size();i++){//注意,这里的判定是i+1<path.size()
  19. ];
  20. if(mp[pre][curr]!=mp[curr][next]) changeCnt++;
  21. pre=curr;//记得更新
  22. }
  23. return changeCnt;
  24. }
  25.  
  26. void dfs(int s)
  27. {
  28. vis[s]=true;
  29. tmpPath.push_back(s);
  30. if(s==e){
  31. int tmpTransfer=getTransferCnt(tmpPath);
  32. < minDistance){
  33. minDistance=tmpPath.size()-;
  34. minTransfer=tmpTransfer;
  35. path=tmpPath;
  36. } == minDistance && tmpTransfer < minTransfer){
  37. minTransfer=tmpTransfer;
  38. path=tmpPath;
  39. }
  40. return;
  41. }
  42. for(auto next:graph[s]){
  43. if(vis[next] == true) continue;
  44. dfs(next);
  45. tmpPath.pop_back();
  46. vis[next]=false;
  47. }
  48. }
  49.  
  50. void printPath(vector<int>& path)
  51. {
  52. //换乘次数为0时,只需要输出起点和终点,单独输出。这里minTransfer是全局变量,在调用该函数前已经确定
  53. ){
  54. ],b=path[path.size()-];//also b=path.back();
  55. printf(]][path[]],a,b);//注意,这里线路不能是mp[a][b],因为站点a、b不一定是相邻的!
  56. return;
  57. }
  58. ];//表示当前这条线路的起始站
  59. ],curr,next;
  60. ;i+<path.size();i++){
  61. curr=path[i],next=path[i+];
  62. if(mp[pre][curr]!=mp[curr][next]) {
  63. printf("Take Line#%d from %04d to %04d.\n",mp[pre][curr],start,curr);
  64. start=curr;//出现换乘,记得更新起始站
  65. }
  66. pre=curr;
  67. }
  68. //输出最后一次换乘至终点的线路
  69. printf(]][path[path.size()-]],start,path[path.size()-]);
  70. }
  71.  
  72. int main()
  73. {
  74. //freopen("pat.txt","r",stdin);
  75. scanf("%d",&k);
  76. ;i<=k;i++){
  77. int pre,curr;
  78. scanf("%d%d",&n,&pre);
  79. ;j<n;j++){
  80. scanf("%d",&curr);
  81. graph[pre].push_back(curr);
  82. graph[curr].push_back(pre);
  83. mp[pre][curr]=mp[curr][pre]=i;
  84. pre=curr;
  85. }
  86. }
  87. scanf("%d",&m);
  88. while(m--){
  89. scanf("%d%d",&s,&e);
  90. //每次查询前千万记得初始化
  91. memset(vis,false,sizeof(vis));
  92. path.clear();
  93. tmpPath.clear();
  94. minDistance=Inf,minTransfer=Inf;
  95. dfs(s);
  96. printf("%d\n",minDistance);
  97. printPath(path);
  98. }
  99. ;
  100. }

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. KNN 算法,以及与Kmeans的简单对比

    KNN与Kmeans感觉没啥联系,但是名字挺像的,就拿来一起总结一下吧. 初学者的总结. KNN是监督学习,Kmeans是无监督学习. KNN用于分类,Kmeans用于聚类. 先说KNN: 对于KNN ...

  2. 认证和授权(Authentication和Authorization)

    什么是OAuth 如今很多网站的功能都强调彼此间的交互,因此我们需要一种简单,标准的解决方案来安全的完成应用的授权,于是,OAuth应运而生,看看官网对其的定义: An open protocol t ...

  3. Ajax基础(三)--eval的使用

    eval的使用: 1.定义和用法 计算某个字符串,并执行其中的js代码 eval(string) string必须,含有表达式或执行语句 string有返回值的话 2.实例 2.1 字符串上该用eva ...

  4. JSON字符串与JSON对象的互相转换

    比如工作中遇到的app强制退出功能的参数问题 首先定义一个JSON字符串 objectStr : String value=UUID.randomUUID().toString();SimpleDat ...

  5. 个人作业4——alpha阶段个人小结

    一.个人总结 在alpha 结束之后, 每位同学写一篇个人博客, 总结自己的alpha 过程: 请用自我评价表:http://www.cnblogs.com/xinz/p/3852177.html 有 ...

  6. winform 中 MessageBox 用法大全

    (转自:http://blog.csdn.net/xuenzhen123/article/details/4808005) MessageBox.Show()共有21中重载方法.现将其常见用法总结如下 ...

  7. 交叉编译工具链介绍《Building Embedded Linux Systems》

    1.前言 配置和编译一个合适的GNU工具链是相对复杂的并且需要很精细的操作,包括你需要对不同软件库之间的依赖关系.它们的各自的任务,不同软件库版本情况都有比较好的了解,编译工具链是一个乏味的工作. 2 ...

  8. 原创:项目管理的理论与实践 讲座的PPT

    业余时间做的两个PPT,曾经给公司同事讲过,PPT内容毕竟还是不够全面,如果有不清楚的地方,欢迎提问 项目管理的理论与实践 虚拟案例-超市管理系统

  9. ubuntu1604-server上安装virtualbox+phpvirtualbox

    1.需要安装phpvirtualbox版本与virtualbox的版本一致,比如phpvirtual5.0.x,需要对应virtualbox 5.0.x 2.需要安装的软件有apache2.php.l ...

  10. let防止变量声明提前

    let可以解决原来js中,一个函数中变量混乱的问题,因为以前var 定义的变量时, {}是不能限制变量作用域的. "use strict"; +function(){ var t= ...