1. 程式人生 > >關於dijkstra求最短路(模板)

關於dijkstra求最短路(模板)

pic poi -s png inf eof oid 顏色 min

嗯....

dijkstra是求最短路的一種算法(廢話,思維含量較低,

並且時間復雜度較為穩定,為O(n^2),

但是註意:!!!! 不能處理邊權為負的情況(但SPFA可以處理,今後會講)

借一個何大佬的圖,因為會在代碼中提到紅、綠、空三種顏色,以及小v,

通過圖會比較清晰一些:

技術分享圖片

思路大約明白了下面就呈上帶批註模板代碼:

 1 #include <cstdio>//dijkstra求最短路
 2 #include <cstring>
 3 #include <algorithm> 
 4 using namespace
std; 5 const int maxn=10005; 6 int g[maxn][maxn], n, m;//g數組用來存圖 7 int dis[maxn], status[maxn];//dis數組中存儲的是從起點到第i個點的最短路長度 8 9 10 /*status//(狀態)用來存點的類型,1.已經求出最短路的點(把它想成紅色,用2來表示) 11 2.是從已經求出最短路的點向外延伸一次就可找到的點(把它想成綠色,用1來表示) 12 3.其余還沒有訪問的,仍沒有色(用0來表示)*/ 13 14 15 //註意每一種算法都要新開一個函數,使代碼簡單易懂 16 void dijkstra(int
start_point) {//dijkstra 最短路寫法: 17 memset(dis, 0x3f, sizeof(dis));//將dis數組中的每一個元素都設為正無窮, 18 //因為後面要用它與更小的最短路進行比較,所以它為最大,且定義為正無窮 19 dis[start_point] = 0;//確定邊界,起點的最短路一定為0 20 status[start_point] = 1;//起點已求出最短路,首先標記為綠色,進行分析 21 for (int ti = 0; ti < n; ++ti) //枚舉n次 22 { 23 int vertex_to_pick = -1
;//將小V初始化為-1(小V即為要找的點) 24 for (int i = 1; i <= n; ++i) //再次進行枚舉 25 { 26 if (status[i] == 1) //如果i點為綠色 27 { 28 if (vertex_to_pick == -1 || dis[i] < dis[vertex_to_pick]) 29 //如果v還沒有被更新或者說是找到一個點i比點v到出發點的距離更近,則也進行更新 30 { 31 vertex_to_pick = i;//進行更新 32 } 33 } 34 } 35 if (vertex_to_pick == -1) { 36 break;//如果找不到下一個點,則退出 37 } 38 status[vertex_to_pick] = 2;//將已經更新好的最近的v添加到red集合 39 for (int i = 1; i <= n; ++i) 40 //從找到的v點進行更新dis數組 41 { 42 if (status[i] == 0 || status[i] == 1) //如果i點還沒有添加到red集合 43 { 44 if (g[vertex_to_pick][i] != -1)// 並且滿足從小v這個點到i點有距離 45 { 46 status[i] = 1;//再次將i點加入綠色集合,進行循環,找到所有相鄰點 47 dis[i] = min(dis[i], dis[vertex_to_pick] + g[vertex_to_pick][i]);//更新i點的最短路 48 } 49 } 50 } 51 } 52 } 53 54 55 56 int main() { 57 //主函數進行輸入、調用、輸出 58 memset(g, -1, sizeof(g)); 59 scanf("%d%d", &n, &m); 60 for (int i = 0; i < m; ++i) { 61 int u, v, w; 62 scanf("%d%d%d", &u, &v, &w); 63 g[u][v] = g[v][u] = w; 64 } 65 dijkstra(1); 66 printf("%d",dis[n]); 67 return 0; 68 }

多背幾遍應該能明白, 反正一直除了更新就是更新.....

關於dijkstra求最短路(模板)