PAT-A 真题 – 1111 Online Map

发布于 / PAT-甲级 / 0 条评论

Input our current position and a destination, an online map can recommend several paths. Now your job is to recommend two paths to your user: one is the shortest, and the other is the fastest. It is guaranteed that a path exists for any request.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers N (2N500), and M, being the total number of streets intersections on a map, and the number of streets, respectively. Then M lines follow, each describes a street in the format:

V1 V2 one-way length time

where V1 and V2 are the indices (from 0 to N1) of the two ends of the street; one-way is 1 if the street is one-way from V1 to V2, or 0 if not; length is the length of the street; and time is the time taken to pass the street.

Finally a pair of source and destination is given.

Output Specification:

For each case, first print the shortest path from the source to the destination with distance D in the format:

Distance = D: source -> v1 -> ... -> destination

Then in the next line print the fastest path with total time T:

Time = T: source -> w1 -> ... -> destination

In case the shortest path is not unique, output the fastest one among the shortest paths, which is guaranteed to be unique. In case the fastest path is not unique, output the one that passes through the fewest intersections, which is guaranteed to be unique.

In case the shortest and the fastest paths are identical, print them in one line in the format:

Distance = D; Time = T: source -> u1 -> ... -> destination

Sample Input 1:

10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
3 4 0 3 2
3 9 1 4 1
0 6 0 1 1
7 5 1 2 1
8 5 1 2 1
2 3 0 2 2
2 1 1 1 1
1 3 0 3 1
1 4 0 1 1
9 7 1 3 1
5 1 0 5 2
6 5 1 1 2
3 5

Sample Output 1:

Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5

Sample Input 2:

7 9
0 4 1 1 1
1 6 1 1 3
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 1 3
3 2 1 1 2
4 5 0 2 2
6 5 1 1 2
3 5

Sample Output 2:

Distance = 3; Time = 4: 3 -> 2 -> 5

题目大意:第一行给定N和M,为城市数和街道数,接着给出M行,每行的格式为:

起点    终点    是否是单向边    路径长度    路上消费的时间

最后一行给出起点和终点,要求规划出起点到终点的最短路径和时间最短路径。

如果最短路径不唯一,则给出消耗时间最少的那条,这个题目保证是唯一的

如果最短时间不唯一,则给出途径城市最少的一条,这个也保证是唯一的。

这是一道较复杂的Dijkstra多解筛选最短路径问题,在筛选路径方面要特别细心。

本题目有两种解法,一种直接在Dijkstra函数中进行筛选,另一种不考虑出现多条路径的情况,将最优前驱结点保存,然后使用DFS筛选路径。使用DFS筛选路径的办法见柳婼学姐的:https://www.liuchuo.net/archives/2407

直接筛选最优路径的代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
#define MAXN 510
#define INF 0x3fffffff

int Dist[MAXN][MAXN], StartP, EndP, Time[MAXN][MAXN];
int N, M;  //N=Point sum, M=>streets sum
vector<int> ShortDist, ShortTime;

int Dijkstra_Dist(){
  int pre[MAXN] = {0};
  bool visited[MAXN] = {false};
  int MinDist[MAXN], MinTime[MAXN];
  fill(MinDist, MinDist + MAXN, INF);
  fill(MinTime, MinTime + MAXN, INF);
  MinTime[StartP] = 0, MinDist[StartP] = 0;
  for(int i = 0; i < N; i++){
    //find MinDist p
    int p = -1, min = INF;
    for(int j = 0; j < N; j++)
      if(visited[j] == false && MinDist[j] < min)
        min = MinDist[j], p = j;
    if(p == -1) return -1;  //Graph not connecty
    visited[p] = true;  //find
    //use p as mid-point update MinDist
    for(int j = 0; j < N; j++){
      if(Dist[p][j] != INF && visited[j] == false){  //have road && not visited
        if(MinDist[p] + Dist[p][j] < MinDist[j]){  //have a better way
          MinDist[j] = MinDist[p] + Dist[p][j];
          pre[j] = p;
          MinTime[j] = MinTime[p] + Time[p][j];
        }else if(MinDist[p] + Dist[p][j] == MinDist[j])  //have a eq-way
          if(MinTime[p] + Time[p][j] < MinTime[j]){  //have short time
            MinTime[j] = MinTime[p] + Time[p][j];
            pre[j] = p;
          }
      }
    } 
  }
  //Save Way
  for(int s = EndP; s != StartP; s = pre[s])
    ShortDist.push_back(s);
  ShortDist.push_back(StartP);
  return MinDist[EndP];
}

int Dijkstra_Time(){
  int pre[MAXN] = {0};
  bool visited[MAXN] = {false};
  int MinTime[MAXN], MinCnt[MAXN];
  fill(MinTime, MinTime + MAXN, INF);
  fill(MinCnt, MinCnt + MAXN, 1);
  MinTime[StartP] = 0;
  for(int i = 0; i < N; i++){
    //find MinTime p
    int p = -1, min = INF;
    for(int j = 0; j < N; j++)
      if(visited[j] == false && MinTime[j] < min)
        min = MinTime[j], p = j;
    if(p == -1) return -1;  //Graph not connecty
    visited[p] = true;  //find
    //use p as mid-point update MinDist
    for(int j = 0; j < N; j++){
      if(Time[p][j] != INF && visited[j] == false){
        if(MinTime[p] + Time[p][j] < MinTime[j]){
          MinTime[j] = MinTime[p] + Time[p][j];
          pre[j] = p;
          MinCnt[j] = MinCnt[p] + 1;
        }else if(MinTime[p] + Time[p][j] == MinTime[j]){
          if(MinCnt[p] + 1 < MinCnt[j]){
            pre[j] = p;
            MinCnt[j] = MinCnt[p] + 1;
          }
        }
      }
    }
  }
  for(int s = EndP; s != StartP; s = pre[s])
    ShortTime.push_back(s);
  ShortTime.push_back(StartP);
  return MinTime[EndP];
}

int main(){
  cin >> N >> M;
  fill(Dist[0], Dist[0] + MAXN * MAXN, INF);
  fill(Time[0], Time[0] + MAXN* MAXN, INF);
  for(int i = 0; i < M; i++){
    int _l, _r, _isOneWay;
    cin >> _l >> _r >> _isOneWay;
    cin >> Dist[_l][_r] >> Time[_l][_r];
    if(!_isOneWay) Dist[_r][_l] = Dist[_l][_r], Time[_r][_l] = Time[_l][_r];
  }
  cin >> StartP >> EndP;
  int ans_MinDist = Dijkstra_Dist();
  int ans_MinTime = Dijkstra_Time();
  if(ShortTime != ShortDist){
    printf("Distance = %d: ", ans_MinDist);
    for(int i = ShortDist.size()-1; i >= 0; i--){
      printf("%d", ShortDist[i]);
      if(i) printf(" -> ");
    }
    cout << endl;
    printf("Time = %d: ", ans_MinTime);
    for(int i = ShortTime.size()-1; i >= 0; i--){
      printf("%d", ShortTime[i]);
      if(i) printf(" -> ");
    }  
  }else{
    printf("Distance = %d; Time = %d: ", ans_MinDist, ans_MinTime);
    for(int i = ShortDist.size()-1; i >= 0; i--){
      printf("%d", ShortDist[i]);
      if(i) printf(" -> ");
    }
  }
  return 0;
}

转载原创文章请注明,转载自: 斐斐のBlog » PAT-A 真题 – 1111 Online Map
目前还没有评论,快来抢沙发吧~