题目分析:

本题的题意比较清晰,就是有一个起点和一个终点,给出m条路径,可能是单向的可能是双向的,同时一条路有两个权重,分别是通过这条路需要的时间和这条路的路径长度,题目需要求出两条路径,一条是在最快的基础上的最短路径,一条是在最短的路径的基础上的通过节点的数量最少的路径(题目保证这两条途径存在,且在各自的情况下唯一,但是这两条路径有可能完全相同,需要合并输出)

解法分析:

通过对题目的分析,我们知道最优的子情况就是全局的最优解,所以我们用两次dijkstra算法,一次求最短路径的情况下通过最少节点的路径记录在pre1中,一次求最快路径的基础上的最短路径,记录在pre2中,最后递归输出路径即可

代码:

  1. 1 #include<stdio.h>
  2. 2 #include<iostream>
  3. 3 #include<algorithm>
  4. 4 #include<cmath>
  5. 5 #include<string.h>
  6. 6 using namespace std;
  7. 7
  8. 8 const int N = 505;
  9. 9 const int M = 0x3f3f3f3f;
  10. 10 int pre1[N];
  11. 11 int pre2[N];
  12. 12 int dist1[N];
  13. 13 int dist2[N];
  14. 14 int mat1[N][N]; //存储距离
  15. 15 int mat2[N][N]; //存储时间
  16. 16 int vis1[N];
  17. 17 int vis2[N];
  18. 18 int num[N];
  19. 19 int n, m;
  20. 20 int min_dist, min_time;
  21. 21 int sta, en;
  22. 22
  23. 23 int minn1(){
  24. 24 int k = -1;
  25. 25 int Min = M;
  26. 26 for(int i = 0; i < n; i++){
  27. 27 if(vis1[i] == 0 && dist1[i] < Min){
  28. 28 Min = dist1[i];
  29. 29 k = i;
  30. 30 }
  31. 31 }
  32. 32 return k;
  33. 33 }
  34. 34
  35. 35 void dijkstra1(){ //计算最短距离 若有相同则选择途经的点最少的
  36. 36 memset(num, 0, sizeof(num));
  37. 37 memset(vis1, 0, sizeof(vis1));
  38. 38 for(int i = 0; i < n; i++) pre1[i] = sta;
  39. 39 for(int i = 0; i < n; i++) dist1[i] = mat1[sta][i];
  40. 40 dist1[sta] = 0;
  41. 41 pre1[sta] = -1;
  42. 42 num[sta] = 1;
  43. 43 for(int i = 1; i <= n; i++){
  44. 44 int k = minn1();
  45. 45 if(k == -1) break;
  46. 46 vis1[k] = 1;
  47. 47 for(int j = 0; j < n; j++){
  48. 48 if(vis1[j] == 0 && dist1[k] + mat1[k][j] < dist1[j]){
  49. 49 dist1[j] = dist1[k] + mat1[k][j];
  50. 50 pre1[j] = k;
  51. 51 num[j] = num[k] + 1;
  52. 52 }else if(vis1[j] == 0 && dist1[k] + mat1[k][j] == dist1[j]){
  53. 53 if(num[j] > num[k] + 1){
  54. 54 num[j] = num[k] + 1;
  55. 55 pre1[j] = k;
  56. 56 }
  57. 57 }
  58. 58 }
  59. 59 }
  60. 60 min_dist = dist1[en];
  61. 61 }
  62. 62
  63. 63 int minn2(){
  64. 64 int k = -1;
  65. 65 int Min = M;
  66. 66 for(int i = 0; i < n; i++){
  67. 67 if(vis2[i] == 0 && dist2[i] < Min){
  68. 68 Min = dist2[i];
  69. 69 k = i;
  70. 70 }
  71. 71 }
  72. 72 return k;
  73. 73 }
  74. 74
  75. 75 void dijkstra2(){ //计算最少时间 若有最少时间相同 则选择最短距离
  76. 76 memset(vis2, 0, sizeof(vis2));
  77. 77 for(int i = 0; i < n; i++) pre2[i] = sta; //因为sta会最先被选中
  78. 78 for(int i = 0; i < n; i++) dist2[i] = mat2[sta][i];
  79. 79 dist2[sta] = 0;
  80. 80 pre2[sta] = -1;
  81. 81 for(int i = 1; i < n; i++){
  82. 82 int k = minn2();
  83. 83 if(k == -1) break;
  84. 84 vis2[k] = 1;
  85. 85 for(int j = 0; j < n; j++){
  86. 86 if(vis2[j] == 0 && dist2[k] + mat2[k][j] < dist2[j]){
  87. 87 dist2[j] = dist2[k] + mat2[k][j];
  88. 88 pre2[j] = k;
  89. 89 }else if(vis2[j] == 0 && dist2[k] + mat2[k][j] == dist2[j]){
  90. 90 if(mat1[pre2[j]][j] > mat1[k][j]){
  91. 91 pre2[j] = k;
  92. 92 }
  93. 93 }
  94. 94 }
  95. 95 }
  96. 96 min_time = dist2[en];
  97. 97 }
  98. 98
  99. 99 void way(int *pre, int x){
  100. 100 if(pre[x] == -1){
  101. 101 printf("%d", x);
  102. 102 return;
  103. 103 }else{
  104. 104 way(pre, pre[x]);
  105. 105 printf(" => %d", x);
  106. 106 }
  107. 107 }
  108. 108
  109. 109 int main(){
  110. 110 scanf("%d%d", &n, &m);
  111. 111 memset(mat1, M, sizeof(mat1));
  112. 112 memset(mat2, M, sizeof(mat2));
  113. 113 for(int i = 1; i <= m; i++){
  114. 114 int a, b, c;
  115. 115 scanf("%d%d%d", &a, &b, &c);
  116. 116 if(c == 1){
  117. 117 scanf("%d%d", &mat1[a][b], &mat2[a][b]);
  118. 118 }else{
  119. 119 scanf("%d%d", &mat1[a][b], &mat2[a][b]);
  120. 120 mat1[b][a] = mat1[a][b]; mat2[b][a] = mat2[a][b];
  121. 121 }
  122. 122 }
  123. 123 scanf("%d%d", &sta, &en);
  124. 124 min_dist = M; min_time = M;
  125. 125 dijkstra1();
  126. 126 dijkstra2();
  127. 127 //如果路径统一则合并输出
  128. 128 int flag = 1;
  129. 129 int temp = en;
  130. 130 while(true){
  131. 131 if(temp == -1) break; //一定是在相等的基础上的-1
  132. 132 if(pre1[temp] == pre2[temp]) temp = pre1[temp];
  133. 133 else{
  134. 134 flag = 0;
  135. 135 break;
  136. 136 }
  137. 137 }
  138. 138 if(flag == 1){
  139. 139 printf("Time = %d; Distance = %d: ", min_time, min_dist);
  140. 140 way(pre1, en);
  141. 141 printf("\n");
  142. 142 }else{
  143. 143 printf("Time = %d: ", min_time);
  144. 144 way(pre2, en);
  145. 145 printf("\n");
  146. 146 printf("Distance = %d: ", min_dist);
  147. 147 way(pre1, en);
  148. 148 printf("\n");
  149. 149 }
  150. 150 return 0;
  151. 151 }

天梯赛练习 L3-007 天梯地图 (30分) Dijkstra的更多相关文章

  1. PAT 天梯赛 是否完全二叉搜索树   (30分)(二叉搜索树 数组)

    将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果. 输入格式: 输入第一行给出一个不超过20的正整数 ...

  2. PAT天梯赛练习 L3-003 社交集群 (30分) DFS搜索

    题目分析: 一共有N个编号为1~1000的人,以及一共有编号为1~1000种不同的兴趣,在题目给出1~N编号的人员每个人喜欢的兴趣的id后,要求统计出不同的人员集合的个数以及每个人员几个的人数从大到小 ...

  3. L3-007 天梯地图 (30 分) dijkstra

    本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线:一条是最短距离的路线.题目保证对任意的查询请求,地图上都至少存在一条可达路线. 输 ...

  4. 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs

    题目分析: 本题我有两种思路,一种是只依靠dijkstra算法,在dijkstra部分直接判断所有的情况,以局部最优解得到全局最优解,另一种是dijkstra + dfs,先计算出最短距离以及每个点的 ...

  5. L3-007 天梯地图 (30分) 最短路+dp

    最短路+dp思路:nuoyanli 520 Let's play computer game 输入样例1: 10 15 0 1 0 1 1 8 0 0 1 1 4 8 1 1 1 5 4 0 2 3 ...

  6. pat天梯赛练习集合 L3-007 天梯地图

    加了一些花的最短路,点的个数为500不需要堆优化,改一下dij的判断条件就可以了. 上代码: #include <iostream> #include <cstring> #i ...

  7. 团体程序设计天梯赛-练习集 L2-001 紧急救援 (25 分)

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...

  8. PAT天梯赛L3-007 天梯地图

    题目链接:点击打开链接 本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线:一条是最短距离的路线.题目保证对任意的查询请求,地图上都至 ...

  9. pat 团体天梯赛 L3-007. 天梯地图

    L3-007. 天梯地图 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题要求你实现一个天梯赛专属在线地图,队员输入自己学校 ...

随机推荐

  1. kafka命令及启动

    默认内网访问,要在外网访问的话,需要在修改config/server.properties中的配置 将listeners和advertised.listeners的值用主机名进行替换,在外用使用jav ...

  2. ado.net使用sqlparameter的方式

    使用sqlparameter的方式,最终执行的sql语句 exec sp_executesql N'select top 1 ID,ZhangHu,MiMa,RID,ShiJian,EndTime,I ...

  3. mac下git连接远程仓库gitee

    一.注册账号 https://gitee.com/ 二.创建仓库 三.创建后显示如下 四.根据页面上展示命令敲一遍就可以了. 备注:注意!!

  4. Oracle数据泵常用命令

    导读:expdp和impdp是oracle数据库之间移动数据的工具,本文简单总结了数据泵的常用命令,希望对大家有帮助.   前言 expdp和impdp是oracle数据库之间移动数据的工具.expd ...

  5. ORA-29701: unable to connect to Cluster Synchronization Service

    修改主机名后,has无法启动,将has启动之后,尝试ASMCA,出现如图提示: 再尝试登陆asm实例,出现日下提示: [oracle@edgzrip2-+ASM ~]$ sqlplus / as sy ...

  6. Spring(二)--IoC&AOP

    IOC 一.IOC概述: 一般指控制反转(inversion of Control),把创建对象的权利交给框架,Ioc容器控制对象,是框架的重要特征,并非是面向对象编程的专用术语.它包括依赖注入(DI ...

  7. UWP 自定义RadioButton实现Tab底部导航

    先看效果: 参照Android的实现方式用RadioButton来实现,但是Uwp的RadioButton并没有安卓的Selector选择器 下面是一个比较简单的实现,如果有同学有更好的实现,欢迎留言 ...

  8. day019python之面向对象基础1

    面向对象基础 目录 面向对象基础 1 面向对象基础 1.1 面向对象的由来 1.2 面向对象编程介绍 1.2.1 回顾面向过程设计 1.2.2 面向对象设计 2 类与对象 2.1 基本使用 2.2 示 ...

  9. Python常用配置文件ini、json、yaml读写总结

    开发项目时,为了维护一些经常需要变更的数据,比如数据库的连接信息.请求的url.测试数据等,需要将这些数据写入配置文件,将数据和代码分离,只需要修改配置文件的参数,就可以快速完成环境的切换或者测试数据 ...

  10. 用Python从头开始构建神经网络

    神经网络已经被开发用来模拟人脑.虽然我们还没有做到这一点,但神经网络在机器学习方面是非常有效的.它在上世纪80年代和90年代很流行,最近越来越流行.计算机的速度足以在合理的时间内运行一个大型神经网络. ...