《資料結構》07-圖6 旅遊規劃
阿新 • • 發佈:2018-11-25
題目
有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。現在需要你寫一個程式,幫助前來諮詢的遊客找一條出發地和目的地之間的最短路徑。如果有若干條路徑都是最短的,那麼需要輸出最便宜的一條路徑。
輸入格式:
輸入說明:輸入資料的第1行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號為0~(N−1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨後的M行中,每行給出一條高速公路的資訊,分別是:城市1、城市2、高速公路長度、收費額,中間用空格分開,數字均為整數且不超過500。輸入保證解的存在。
輸出格式:
在一行裡輸出路徑的長度和收費總額,數字間以空格分隔,輸出結尾不能有多餘空格。
輸入樣例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
輸出樣例:
3 40
分析
權值有兩個,用兩個圖儲存就好,最短路徑直接上 Dijkstra 演算法,稍微改改就 ok
#include<iostream>
#define MaxVertex 505
#define INF 100000
typedef int Vertex;
int N; // 頂點數
int M; // 邊
int S; // Source
int D; // Destination
int dist[MaxVertex]; // 距離
int cost[MaxVertex]; // 費用
bool collected[MaxVertex]; // 選中情況
int value[MaxVertex][MaxVertex]; // 收費
int G[MaxVertex][MaxVertex];
using namespace std;
void build(){
Vertex v1,v2,w1,w2;
cin>>N>>M>>S>>D;
for(Vertex i=0;i<N;i++){
for(Vertex j=0;j< N;j++){
G[i][j] = INF;
value[i][j] = INF;
}
cost[i] = 0;
collected[i] = false;
dist[i] = INF;
}
for(int i=0;i<M;i++){
cin>>v1>>v2>>w1>>w2;
G[v1][v2] = w1;
G[v2][v1] = w1;
value[v1][v2] = w2;
value[v2][v1] = w2;
}
}
// 初始化源點資訊
void InitSource(){
dist[S] = 0;
collected[S] = true;
for(Vertex i=0;i<N;i++)
if(G[S][i]){
dist[i] = G[S][i];
cost[i] = value[S][i];
}
}
// 查詢未被收錄中dist最小的點
Vertex FindMin(){
int min = INF;
Vertex xb = -1;
for(Vertex i=0;i<N;i++)
if(S!=i && !collected[i] && dist[i] < min){
min = dist[i];
xb = i;
}
return xb;
}
void Dijkstra(){
InitSource();
while(1){
Vertex v = FindMin();
if(v==-1)
break;
collected[v] = true;
for(Vertex w=0;w<N;w++)
if(!collected[w] && G[v][w])
if(dist[v] + G[v][w] < dist[w]){ // 如果有路徑更短
dist[w] = dist[v] + G[v][w];
cost[w] = cost[v] + value[v][w];
}else if(dist[v] + G[v][w] == dist[w] && cost[v] + value[v][w] < cost[w]){ // 如果路徑一樣長,選擇費用更少
cost[w] = cost[v] + value[v][w];
}
}
}
int main(){
build();
Dijstra();
cout<<dist[D]<<" "<<cost[D];
return 0;
}