題目描述
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。
輸入輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t;起點s,終點t。n和m為0時輸入結束。
(1輸出
輸出 一行有兩個數, 最短距離及其花費。
樣例輸入 copy
3 21 2 5 6
2 3 4 5
1 30 0
樣例輸出 copy
9 11
提示拿到這題,第一印象就是最短路徑問題(題目寫得清清楚楚)。當然,你可以直接套用最短路徑的解法。不過這裡我要給大家介紹另一種解法,同樣是圖論裡的演算法——深度優先搜尋。
從起點開始進行深度優先搜尋,當搜尋的結點到達終點時檢視路徑總長度與花費是否比已經得到的最短路徑和最小花費小,如果要小的話就使用當前的路徑和花費取代最短路徑和最小花費。
當遍歷到終點時是否就結束了?非也,還需要從其他路徑遍歷,判斷其他路徑是否又更短花費更小的。這裡就需要用到回溯了。所謂回溯,就是還需要往回走來走其他的路徑。那麼會不會進入迴圈狀態呢?對遍歷過的結點進行標記就能夠杜絕迴圈。當然需要在回溯時取消之前的標記。
一般的想法,用迪傑斯特拉最短路徑寫的。加了乙個記錄花費的陣列和變數。
#include
#include
using
namespace std;
int inf=
0x3fffffff
;struct node};
vectorg[
1001];
bool visit[
1001];
int d[
1001
],e[
1001];
int n;
void
dij(
int s)
d[s]=0
; visit[s]
=true
;for
(i=1
; iif(u==-1
)return
; visit[u]
=true
;for
(j=0
; j.size()
; j++
)else
if(visit[m]
==false
&&d[u]
+g[u]
[j].distance==d[m]
&&e[u]
+g[u]
[j].pay}}
intmain()
scanf
("%d %d"
,&s,
&t);
dij(s)
;printf
("%d %d\n"
,d[t]
,e[t]);
}return0;
}
根據題目中的提示,用深度優先搜尋寫的。
#include
#include
using
namespace std;
int inf=
0x3fffffff
;int distance,pay;
struct node};
vectorg[
1001];
bool visit[
1001];
int n,t,mind,minp;
void
dfs(
int s)
else
if(distance==mind&&payreturn;}
for(i=
0; i.size()
; i++)}
}int
main()
scanf
("%d %d"
,&s,
&t);
dfs(s)
;printf
("%d %d\n"
,mind,minp);}
return0;
}
問題 E 最短路徑問題
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。輸入n,m,點的編號是1 n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t 起點s,...
問題 E 最短路徑問題
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。輸入n,m,點的編號是1 n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數s,t 起點s,終...
最短路 最短路徑問題
題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。input 共有n m 3行,其中 第一行為乙個整數n。第2行...