求最短路徑-----迪傑斯特拉演算法
3),迪傑斯特拉演算法(解決單源最短路徑)
基本思想:每次找到離源點(如1號結點)最近的一個頂點,然後以該頂點為中心進行擴充套件,最終得到源點到其餘所有點的最短路徑。
基本步驟:1,設定標記陣列book[]:將所有的頂點分為兩部分,已知最短路徑的頂點集合P和未知最短路徑的頂點集合Q,很顯然最開始集合P只有源點一個頂點。book[i]為1表示在集合P中;
2,設定最短路徑陣列dst[]並不斷更新:初始狀態下,令dst[i] = edge[s]i,很顯然此時dst[s]=0,book[s]=1。此時,在集合Q中可選擇一個離源點s最近的頂點u加入到P中。並依據以u為新的中心點,對每一條邊進行鬆弛操作(鬆弛是指由結點s–>j的途中可以經過點u,並令dst[j]=min{dst[j], dst[u]+edge[u][j]}),並令book[u]=1;
3,在集合Q中再次選擇一個離源點s最近的頂點v加入到P中。並依據v為新的中心點,對每一條邊進行鬆弛操作(即dst[j]=min{dst[j], dst[v]+edge[v][j]}),並令book[v]=1;
4,重複3,直至集合Q為空。
例1:給你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<n<=1000, 0<m<100000, s != t)
輸出:輸出一行,有兩個數, 最短距離及其花費。
分析:由於每條邊有長度d和花費p,最好構建邊結構體存放,此外可以使用鄰接連結串列,使用鄰接連結串列時需要將上面的核心程式碼修改幾個地方:
1,初始化dst[]時使用結點1的鄰接連結串列;
2,更新最短路徑陣列時,k的範圍由1n變為1edge[u].size()。先採用鄰接矩陣解決此題,再使用鄰接表解決此題,兩種方法的思路都一樣:初始化鄰接矩陣或鄰接連結串列,並
初始化最短路徑陣列dst ----> n-1輪邊的鬆弛中,先找到離新源點最近的中心點u,之後根據中心點u為轉折點來更新路徑陣列。
使用鄰接矩陣求解:
//***對於無向圖,輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數s,t;起點s,終點 t。***/
//***n和m為 0 時輸入結束。(1<n<=1000, 0<m<100000, s != t) 輸出:輸出一行,有兩個數, 最短距離及其花費。***/
#include<bits/stdc++.h>
using namespace std;
#define nmax 1001
#define inf 99999999
struct Edge{
int len;//邊長
int cost;//權重
};
Edge edge[nmax][nmax];//鄰接矩陣
int dst[nmax];//最短路徑陣列
int spend[nmax];//最小花費陣列
int book[nmax];//標記走過的陣列
int n, m, stNode, enNode;
int main(){
while(cin >> n >> m && n != 0 && m != 0){
int a, b, i, j;
//構建鄰接矩陣和最短路徑陣列
//初始化
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
edge[i][j].cost = 0;
edge[i][j].len = inf;
}
edge[i][i].len = 0;
}
while(m--){//初始化
cin >> a >> b;
cin >> edge[a][b].len >> edge[a][b].cost;
edge[b][a].len = edge[a][b].len;
edge[b][a].cost = edge[a][b].cost;
}
cin >> stNode >> enNode;//開始的點和結束的點
//初始化陣列
for(i = 1; i <= n; i++){
dst[i] = edge[stNode][i].len;
spend[i] = edge[stNode][i].cost;
}
memset(book, 0, sizeof(book));
book[stNode] = 1;
//開始迪傑斯特拉演算法,進行剩餘n-1次鬆弛
int k;
for(k = 1; k <= n-1; k++){
//找離源點最近的頂點u
int minNode, min = inf;
for(i = 1; i <= n; i++){
if(book[i] == 0 && min > dst[i] /* || min == dst[i]&& edge[stNode][min].cost > edge[stNode][i].cost*/){
min = dst[i];
minNode = i;
}
}
book[minNode] = 1;//易錯點1,錯寫成book[i]=1
//以中心點u為轉折點來更新路徑陣列和花費陣列
for(i = 1; i <= n; i++){
if(book[i] == 0 && dst[i] > dst[minNode] + edge[minNode][i].len || dst[i] == dst[minNode] + edge[minNode][i].len && spend[i] > spend[minNode] + edge[minNode][i].cost){
dst[i] = dst[minNode] + edge[minNode][i].len;//易錯點2,錯寫成dst[i]+
spend[i] = spend[minNode] + edge[minNode][i].cost;
}
}
}
cout << dst[enNode] << setw(3) << spend[enNode] << endl;
}
return 0;
}
轉載
相關文章
- 最短路徑—Dijkstra(迪傑斯特拉)演算法演算法
- 最短路-迪傑斯特拉(dijkstra)
- C++迪傑斯特拉演算法求最短路徑的詳細解釋C++演算法
- 路徑規劃演算法 - 求解最短路徑 - Dijkstra(迪傑斯特拉)演算法演算法
- 迪傑斯特拉與spfa
- dijkstra迪傑斯特拉演算法(鄰接表法)演算法
- Dijkstra迪傑斯特拉求最短路和最短路的條數和各個點權值的最大值
- 資料結構與演算法——迪傑斯特拉(Dijkstra)演算法資料結構演算法
- 資料結構學習筆記-迪傑斯特拉演算法資料結構筆記演算法
- 程式設計師必須會的基本演算法8-Dijkstra演算法(迪傑斯特拉演算法)程式設計師演算法
- L3-008 天梯團體賽 喊山 (30分) (vector容器的迪傑斯特拉解法)
- 求最短路徑——DFS+Floyd演算法演算法
- 8.14 (河南牛客萌新賽 線段樹 ,ST求區間最值,迪傑斯特拉建正反圖,bfs+二分,模擬)+狀態bfs搜素
- 最短路:求最長最短路
- 矩陣求最短路徑矩陣
- 演算法(四):圖解狄克斯特拉演算法演算法圖解
- 最短路徑演算法演算法
- Djikstra最短路徑演算法演算法
- 最短路徑(Dijskra演算法)JS演算法
- 最短路徑(Floyd演算法)演算法
- 最短路徑之Floyd演算法演算法
- 最短路徑之Dijkstra演算法演算法
- [MATLAB]最短路徑Floyd演算法Matlab演算法
- 最短路徑演算法總結演算法
- 《演算法圖解》總結第 7 章:狄克斯特拉演算法演算法圖解
- SciTech-BigDataAIML-Algorithm-Heuristic啟發式- 帶weight(權重)Graph(圖,無向)的最優路線規劃 : Dijkstra迪傑斯特拉演算法"由節點路線無向Graph"得出"Routing Table(路由表)"AIGo演算法路由
- 最短路徑問題 (dijkstra演算法)演算法
- 幾個最短路徑的演算法演算法
- Floyd演算法(計算最短路徑)演算法
- 單源最短路徑-Dijkstra演算法演算法
- 最短路徑——Dijkstra演算法和Floyd演算法演算法
- 多源最短路徑演算法:Floyd演算法演算法
- 0016:單源最短路徑(dijkstra演算法)演算法
- 圖的最短路徑演算法彙總演算法
- 最短路徑--dijkstra演算法、弗洛伊德(Floyd)演算法(帶路徑輸出)演算法
- 6.4.2最短路徑
- 圖 - 最短路徑
- [最短路徑問題]Dijkstra演算法(含還原具體路徑)演算法