1. 程式人生 > >HDU 2680 Choose the best route

HDU 2680 Choose the best route

Choose the best route

  One day , Kiki wants to visit one of her friends. As she is liable to carsickness , she wants to arrive at her friend’s home as soon as possible . Now give you a map of the city’s traffic route, and the stations which are near Kiki’s home so that she can take. You may suppose Kiki can change the bus at any station. Please find out the least time Kiki needs to spend. To make it easy, if the city have n bus stations ,the stations will been expressed as an integer 1,2,3…n.

Input

  There are several test cases. 
  Each case begins with three integers n, m and s,(n<1000,m<20000,1=<s<=n) n stands for the number of bus stations in this city and m stands for the number of directed ways between bus stations .(Maybe there are several ways between two bus stations .) s stands for the bus station that near Kiki’s friend’s home. 
  Then follow m lines ,each line contains three integers p , q , t (0<t<=1000). means from station p to station q there is a way and it will costs t minutes . 
  Then a line with an integer w(0<w<n), means the number of stations Kiki can take at the beginning. Then follows w integers stands for these stations. 
Output

  The output contains one line for each data set : the least time Kiki needs to spend ,if it’s impossible to find such a route ,just output “-1”.Sample Input

5 8 5
1 2 2
1 5 3
1 3 4
2 4 7
2 5 6
2 3 5
3 5 1
4 5 1
2
2 3
4 3 4
1 2 3
1 3 4
2 3 2
1
1

Sample Output

1
-1

解題思路:
  本題有多組測試資料,每組第一行給出三個整數,分別為車站數量n,公交線路數m,朋友家s,之後m行為公交線路資訊,每行包含3個整數分別為起點站p,終點站q,需要時間t,輸入完公交線路後下一行給出一個整數w代表可以使用的起點站數量,再下一行給出w個整數,為可用起點。要求輸入到達朋友家少需要多長時間。

  通過分析可以得知本題是最短路問題,我們使用dijkstra尋找最短時間

  用一個數組minTime儲存從起點到所有公交站的最短時間,一個布林陣列vis記錄是否固定對應公交站的最短時間。初始狀態將到所有公交站的最短時間都視為無窮大,從起點開始標記,記錄起點到自己的最短時間為0,之後每次找到並固定到達起點用時最短的公交車站,固定一個公交站後檢視以站為媒介是否能使還沒有固定的車站到達起點的時間減短,如果能減短,將優化後的時間記入該車站對應的minTime中。

  由於本題初始可用車站有多個點,若依次以這些點為起點進行dijkstra運算會消耗大量的時間,我們不妨設立一個“超級原點”即(0,0)點,之後讓“超級原點”到達所有初始可用車站的時間都為0,以“超級原點”為起點進行dijkstra運算即可得到前往所有車站的最短時間。

AC程式碼

  

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int inf = 0x3fffffff; //無窮大
 4 const int maxn = 1e4+100;
 5 int G[maxn][maxn];  //G為車站鄰接矩陣
 6 int minTime[maxn];  //minTime記錄起點到每個車站的最短時間
 7 bool vis[maxn] = {false};   //vis記錄抵達當前車站的最短時間是否已經固定
 8 int n, m;   //n為車站數,m為線路數
 9 bool dijkstra(int s){   //傳入終點
10     //由於可能出現無法抵達朋友家的情況(即起點終點不連通)
11     //dijkstra設為bool型別若不連通返回false
12     memset(vis, false, sizeof(vis));    //初始化所有車站為不固定
13     fill(minTime, minTime + n + 1, inf);    //初始化起點到所有車站的最短時間為無窮大
14     minTime[0] = 0; //起點到本身最短時間為0
15     for(int i = 0; i <= n; i++){    //遍歷所有車站
16         int minStation = -1;    //minStation記錄當前到起點用時最短的點
17         int nowMinTime = inf;   //nowMinTime記錄起點到當前用時最短的點所需時間
18         for(int j = 0; j <= n; j++){    //尋找minStation與nowMinTime
19             if(!vis[j] && minTime[j] < nowMinTime){
20                 minStation = j;
21                 nowMinTime = minTime[j];
22             }
23         }
24         if(minStation == -1){   //如果找不到用時最短的點證明之後的點與起點不連通
25             if(minTime[s] != inf)   //判斷朋友家與起點是否連通
26                 return true;
27             else
28                 return false;
29         }
30         vis[minStation] = true; //將當前到起點用時最短的車站到起點的時間固定
31         for(int j = 0; j <= n; j++){    //以該站為媒介判斷是否能優化
32             if(!vis[j] && G[minStation][j] != inf && minTime[j] > G[minStation][j] + minTime[minStation]){
33                 //如果能找到
34                 //1、時間未固定
35                 //2、與該站之間有公交線路
36                 //3、以該點為媒介可以優化到起點的時間
37                 //就進行優化
38                 minTime[j] = G[minStation][j] + minTime[minStation];
39             }
40         }
41     }
42     return true;
43 }
44 int main()
45 {
46     int s;
47     while(scanf("%d%d%d", &n, &m, &s) != EOF){  //輸入車站數,線路數,朋友家所在的公交站
48         for(int i = 0; i <= n; i++){    //初始化每個公交站到除了自己之外的所有站的耗時都為無窮大
49             for(int j = 0; j <= n; j++){
50                 i == j ? G[i][j] = 0 : G[i][j] = inf;
51             }
52         }
53         for(int i = 0; i < m; i++){
54             int p, q, t;
55             scanf("%d%d%d", &p, &q, &t);    //輸入公交線路線路資訊
56             if(G[p][q] < t) //可能出現兩個站之間有多條線路的情況,只取耗時最短的一條
57                 continue;
58             G[p][q] = t;
59         }
60         int w;  //輸入初始可用車站數
61         scanf("%d", &w);
62         for(int i = 0; i < w; i++){
63             int temp;
64             scanf("%d", &temp); //輸入初始可用車站
65             G[0][temp] = 0; //超級原點到初始可用車站耗時為0
66         }
67         if(dijkstra(s)){    //如果朋友家可達
68             printf("%d\n", minTime[s]); //輸出最短耗時
69         }else{
70             printf("-1\n"); //不可達輸出-1
71         }
72     }
73     return 0;
74 }