1. 程式人生 > >PTA天梯 L3-007 天梯地圖

PTA天梯 L3-007 天梯地圖

ios ng- 如果 應該 前驅 ++ mes str 頂點

L3-007 天梯地圖

題目:

本題要求你實現一個天梯賽專屬在線地圖,隊員輸入自己學校所在地和賽場地點後,該地圖應該推薦兩條路線:一條是最快到達路線;一條是最短距離的路線。題目保證對任意的查詢請求,地圖上都至少存在一條可達路線。

輸入格式:

輸入在第一行給出兩個正整數N(2 N ≤ 500)和M,分別為地圖中所有標記地點的個數和連接地點的道路條數。隨後M行,每行按如下格式給出一條道路的信息:

V1 V2 one-way length time

其中V1V2是道路的兩個端點的編號(從0到N-1);如果該道路是從V1V2的單行線,則one-way為1,否則為0;length

是道路的長度;time是通過該路所需要的時間。最後給出一對起點和終點的編號。

輸出格式:

首先按下列格式輸出最快到達的時間T和用節點編號表示的路線:

Time = T: 起點 => 節點1 => ... => 終點

然後在下一行按下列格式輸出最短距離D和用節點編號表示的路線:

Distance = D: 起點 => 節點1 => ... => 終點

如果最快到達路線不唯一,則輸出幾條最快路線中最短的那條,題目保證這條路線是唯一的。而如果最短距離的路線不唯一,則輸出途徑節點數最少的那條,題目保證這條路線是唯一的。

如果這兩條路線是完全一樣的,則按下列格式輸出:

Time = T; Distance = D: 起點 => 節點1 => ... => 終點

輸入樣例1:

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

輸出樣例1:

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

輸入樣例2:

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

輸出樣例2:

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

解題思路:

首先是建圖,然後求兩次最短路徑。

因為求最快的路時要用到最短的路,所以先求最短的路,再求最快的路。

pre記錄每個節點的上一個節點來記錄路徑。

用到的是 圖的最短路徑算法,這裏用的是dijkstra算法。

代碼:

起點StartLen[k]表示從startk的最短路徑,用preL[k]記錄k的前驅點。

根據題意,變異dijkstra算法:如果最快到達路線不唯一,則輸出幾條最快路線中最短的那條。如果最短距離的路線不唯一,則輸出途徑節點數最少的那條。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <stack>
  4 #include <iostream>
  5 #include <algorithm>
  6 #define N 505
  7 using namespace std;
  8 
  9 int maxint = 9999999;
 10 int n, Start, End, i, j;
 11 bool vis[N];    //標記是否訪問過
 12 int mapL[N][N];    //記錄距離的伴隨矩陣
 13 int mapT[N][N];    //記錄時間的伴隨矩陣
 14 int Len[N];        //Start到k 的最短距離
 15 int Time[N];    //Start到k 的最少時間
 16 int preL[N];    //最短距離路徑前驅
 17 int preT[N];    //最少時間路徑前驅
 18 
 19 //Dijstra算法求最短距離,修改後以符合題意
 20 void Dijstra_Len(){
 21     int step[N];
 22     memset(step, 0, sizeof(step));
 23     step[Start] = 1;
 24     //step記錄節點數
 25     memset(vis, 1, sizeof(vis));
 26     Len[Start] = 0;
 27     while(1){
 28         int minl = maxint, k;
 29         //在沒有被訪問過的點中找一個頂點k,使len[k]最小
 30         for(i = 0;i < n; i++){
 31             if(vis[i] && minl > Len[i]){
 32                 minl = Len[i];
 33                 k = i;
 34             }
 35         }
 36         //如果所有點都已經訪問過,則結束遍歷
 37         if(minl == maxint)break;
 38         //頂點k 標記為已確定(start 到達k 的最短路徑)
 39         vis[k] = 0;
 40         //遍歷與k 相連的每個未確定最短路徑的頂點j
 41         for(i = 0;i < n; i++){
 42             int d = Len[k] + mapL[k][i];
 43             if(vis[i] && Len[i] > d){
 44                 Len[i] = d;
 45                 preL[i] = k;
 46                 step[i] = step[k]+1;
 47             //當路徑距離相等時,優先記錄節點數少的路徑
 48             }else if(vis[i] && Len[i] == d && step[k]+1 < step[i]){
 49                 preL[i] = k;
 50                 step[i] = step[k]+1;
 51             }
 52         }
 53     }
 54 }
 55 
 56 //Dijstra算法求最少時間,修改後以符合題意
 57 void Dijstra_Time(){
 58     memset(vis, 1, sizeof(vis));
 59     //用於記錄距離長度
 60     int dis[N];
 61     for(i = 0;i < n; i++)
 62         dis[i] = mapL[Start][i];
 63     Time[Start] = 0;
 64     dis[Start] = 0;
 65     while(1){
 66         int minl = maxint, k;
 67         for(i = 0;i < n; i++){
 68             if(vis[i] && minl > Time[i]){
 69                 minl = Time[i];
 70                 k = i;
 71             }
 72         }
 73         if(minl == maxint)break;
 74         vis[k] = 0;
 75         for(i = 0;i < n; i++){
 76             int t = Time[k]+mapT[k][i];
 77             int d = dis[k]+mapL[k][i];
 78             if(vis[i] && Time[i] > t){
 79                 dis[i] = d;
 80                 Time[i] = t;
 81                 preT[i] = k;
 82             //當時間相同時,保存其中距離最短的
 83             }else if(vis[i] && Time[i] == t && dis[i] > d){
 84                 dis[i] = d;
 85                 preT[i] = k;
 86             }
 87         }
 88     }
 89 }
 90 
 91 int main(){
 92     memset(preL, -1, sizeof(preL));
 93     memset(preT, -1, sizeof(preT));
 94     int m;
 95     cin >> n >> m;
 96     for(i = 0;i < n; i++){
 97         Len[i] = maxint;
 98         Time[i] = maxint;
 99         for(int j = 0;j < n;++j){
100             mapL[i][j] = maxint;
101             mapT[i][j] = maxint;
102         }
103     }
104     while(m--){
105         int x, y, t;
106         cin >> x >> y >> t;
107         cin >> mapL[x][y] >> mapT[x][y];
108         if(!t){
109             mapL[y][x] = mapL[x][y];
110             mapT[y][x] = mapT[x][y];
111         }
112     }
113     cin >> Start >> End;
114     Dijstra_Len();
115     Dijstra_Time();
116     //取出前驅節點裏保存的路徑,裝入stack中
117     stack<int> bestT, bestL;
118     i = End;
119     while(i != Start){
120         bestT.push(i);
121         i = preT[i];
122     }
123     i = End;
124     while(i != Start){
125         bestL.push(i);
126         i = preL[i];
127     }
128     //按題意要求輸出
129     if(bestL == bestT){
130         printf("Time = %d; Distance = %d: %d",Time[End], Len[End], Start);
131         while(!bestL.empty()){
132             int t = bestL.top();
133             cout << " => " << t;
134             bestL.pop();
135         }cout << endl;
136     }else {
137         cout << "Time = " << Time[End] << ": " << Start;
138         while(!bestT.empty()){
139             int t = bestT.top();
140             cout << " => " << t;
141             bestT.pop();
142         }
143         cout << endl << "Distance = " << Len[End] << ": " << Start;
144         while(!bestL.empty()){
145             int t = bestL.top();
146             cout << " => " << t;
147             bestL.pop();
148         }cout << endl;
149     }
150 
151     return 0;
152 }

PTA天梯 L3-007 天梯地圖