7-1 城市間緊急救援 (25 分)(最短路徑:斯特拉算法)


7-1 城市間緊急救援 (25 分)

作為一個城市的應急救援隊伍的負責人,你有一張特殊的全國地圖。在地圖上顯示有多個分散的城市和一些連接城市的快速道路。每個城市的救援隊數量和每一條連接兩個城市的快速道路長度都標在地圖上。當其他城市有緊急求助電話給你的時候,你的任務是帶領你的救援隊盡快趕往事發地,同時,一路上召集盡可能多的救援隊。

輸入格式:

輸入第一行給出4個正整數N、M、S、D,其中N(2N500)是城市的個數,順便假設城市的編號為0 ~ (N1);M是快速道路的條數;S是出發地的城市編號;D是目的地的城市編號。

第二行給出N個正整數,其中第i個數是第i個城市的救援隊的數目,數字間以空格分隔。隨后的M行中,每行給出一條快速道路的信息,分別是:城市1、城市2、快速道路的長度,中間用空格分開,數字均為整數且不超過500。輸入保證救援可行且最優解唯一。

輸出格式:

第一行輸出最短路徑的條數和能夠召集的最多的救援隊數量。第二行輸出從S到D的路徑中經過的城市編號。數字間以空格分隔,輸出結尾不能有多余空格。

輸入樣例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

輸出樣例:

2 60
0 1 3

  1 #include<stdio.h>
  2 #include<iostream>
  3 using namespace std;
  4 struct
  5 {
  6     int visit;//該城市是否已作為最近點被訪問
  7     int minlen;//該城市到救援城市的距離
  8     int man;//在該城市已經集合的救援隊人數
  9     int cont;//到該城市有幾條同長度最短路徑
 10     int pre;//到該城市的前一個前一個城市序號
 11 }Visit[521];
 12 int Graph[521][521];//城市地圖
 13 int cityman[521];//每個城市的救援隊數量
 14 void InitVisit(int N, int S, int D)//初始化Visit
 15 {
 16     for(int i=0; i<N; i++){
 17         Visit[i].minlen = 521;//將每個城市的最短路徑都設為最大,521
 18         Visit[i].visit = 0;//都設為未訪問
 19         Visit[i].cont = 1;//最短路徑數量都設為1
 20         Visit[i].man = 0;//將救援隊數量都初始化為0
 21     }
 22     //Visit[S].man = cityman[S];
 23     Visit[S].visit = 1;
 24 }
 25 void InitGraph(int N, int M)//初始化城市地圖
 26 {
 27     for(int i=0; i<=N; i++)
 28         for(int j=0; j<=N; j++)
 29         Graph[i][j] = 521;//初始化任意兩個城市間的距離為521
 30     int v1, v2, s;
 31     for(int i=0; i<M; i++){//輸入城市地圖
 32         cin>>v1>>v2>>s;
 33         Graph[v1][v2] = s;
 34         Graph[v2][v1] = s;
 35     }
 36 }
 37 int DKS_GetMi(int N, int S, int D)//根據迪傑斯特拉算法求單源點最短路徑
 38 {
 39     for(int i=0; i<=N; i++){//根據城市地圖更新Visit
 40         Visit[i].minlen=Graph[i][S];
 41         if(Graph[i][S]!=521){
 42             Visit[i].man = cityman[i]+cityman[S];
 43             Visit[i].pre = S;//如果到源城市有路徑,則設該城市的前一個城市為源城市
 44         }
 45     }
 46 
 47     for(int j=1; j<N; j++){//循環N-1次,每次找到剩余城市中距離最近的
 48         int minpoint = N;//第N個點已設置為無窮遠
 49         for(int i=0; i<N; i++){//找到未訪問的最近的城市
 50             if(Visit[i].minlen<Visit[minpoint].minlen&&!Visit[i].visit)
 51                minpoint = i;
 52         }
 53         Visit[minpoint].visit=1;//將找到的最近的城市設置為已訪問
 54         for(int i=0; i<N; i++){//根據找到的最近點的城市更新其他城市的距離
 55             if(!Visit[i].visit){
 56                 if(Visit[i].minlen>Visit[minpoint].minlen+Graph[i][minpoint]){//若有更短距離則更新
 57                     Visit[i].minlen = Visit[minpoint].minlen+Graph[i][minpoint];//更新最短距離
 58                     Visit[i].man = Visit[minpoint].man+cityman[i];//修改聚集的救援隊人數:上一個城市集合的數量加上分配在該城市的數量
 59                     Visit[i].pre = minpoint;//設置上一個城市的序號
 60                     Visit[i].cont = Visit[minpoint].cont;//更新同長度路徑數量:為上一個城市的同長度路徑數量
 61                 }
 62                 else if(Visit[i].minlen==Visit[minpoint].minlen+Graph[i][minpoint]){//若路徑相等,則更新有關信息
 63                     Visit[i].cont += Visit[minpoint].cont;//相等路徑數量為:原來的數量 + 新路徑中到前一個城市的相等路徑數量
 64                     if(Visit[i].man<cityman[i]+Visit[minpoint].man){//選擇能集合救援隊最多的
 65                         Visit[i].man = cityman[i]+Visit[minpoint].man;
 66                         Visit[i].pre = minpoint;
 67                     }
 68                 }
 69             }
 70         }
 71     }
 72 
 73 }
 74 int main()
 75 {
 76     int N, M, S, D;
 77     cin>>N>>M>>S>>D;
 78     for(int i=0; i<N; i++){
 79         cin>>cityman[i];
 80     }
 81     InitVisit(N, S, D);
 82     InitGraph(N,M);
 83     DKS_GetMi(N,S,D);
 84     cout<<Visit[D].cont<<" "<<Visit[D].man<<endl;
 85     // 建立數組存儲路徑序列
 86     int a[521];
 87     int len = 520;
 88     int pre = D;
 89     while(pre!=S){//從目的地找前一個城市,一直找到源城市
 90         a[len] = pre;
 91         pre = Visit[pre].pre;
 92         len--;
 93     }
 94     a[len] = S;
 95     for(int i=len; i<521; i++){
 96         if(i==len)
 97             cout<<a[i];
 98         else
 99             cout<<" "<<a[i];
100     }
101 
102 }
103 /*新增測試數據
104 5 6 0 4
105 20 30 40 10 20
106 0 1 1
107 0 2 1
108 0 3 1
109 1 4 2
110 2 4 2
111 3 4 2
112 */

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM