【数据机构】最短路径之Dijkstra算法(迪克斯特拉算法)
生活随笔
收集整理的這篇文章主要介紹了
【数据机构】最短路径之Dijkstra算法(迪克斯特拉算法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
最短路徑問題是圖論中的一個經典問題。
最短路徑問題就是求圖G(V,E)中某兩個特定頂點間最短的路徑長度。
本文介紹求最短路徑的一個經典算法——Dijkstra算法,
它由荷蘭圖靈獎獲得者、計算機科學家Dijkstra于1959年提出。
該算法能夠有效地計算出某個特定頂點(稱為源點),到其余所有頂點的最短路徑,
即它能夠很好地解決單源最短路徑問題。
?
1. 問題介紹
1.1 題目描述
從一個城鎮抵達另一個城鎮時,有不同的路徑可以選擇,請幫助行人選擇最短路徑。 現在,已知起點和終點,請計算出要從起點到終點,最短需要行走多少距離。1.2 輸入
本題包含多組數據。 每組數據第一行包含兩個正整數N和M(0<N<200,0<M<1000),分別代表現有城鎮的規模和已修建的道路的數目。城鎮分別以0~N-1編號。 接下來是M行道路信息,每一行有三個整數A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城鎮A和城鎮B之間有一條長度為X的雙向道路。 再接下來的下一行有兩個整數S,T(0<=S,T<N),分別代表起點和終點。1.3 輸出
對于每組數據,請在一行中輸出最短需要行走的距離。 若不存在從S到T的路線,則輸出-1。1.4 樣例輸入
3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 21.5 樣例輸出
2 -1?
2. 解決方案
我們不作證明的給出以下結論:
- 最短路徑的特點
- 源點到該點相鄰(只含一條弧),該弧的權值最小;
- 若已知源點到目標點的最短路徑,則源點到達該路徑中其他結點的路徑,也是最短路徑。
?
下面給出Dijkstra算法:
- Dijkstra算法在運行過程中將頂點集合V分成兩個集合S和T。
- ?S:已確定的頂點集合,初始只含源點s
- ?T=V-S:尚未確定的頂點集合
- 算法反復從集合T中選擇當前到源點s最近的頂點u,將u加入集合S,然后對所有從u發出的邊進行松弛操作。
?
3. 代碼
又到了重要的代碼環節。。上干貨
//注意該代碼是無向圖 //如果是有向圖,在初始化圖的時候只保留from->to 即可#include<iostream> #include<cstdio> #include<vector> #include<cstring> #include<queue> #include<climits>using namespace std;const int MAXN = 200; const int INF = INT_MAX;struct Edge {int to;int length;Edge(int t, int l) :to(t), length(l) {} };struct Point {int number;int distance;Point(int n, int d) :number(n), distance(d) {}friend bool operator < (Point a, Point b){return a.distance > b.distance;} };vector<Edge> graph[MAXN]; int dis[MAXN]; bool visit[MAXN];void Dijkstra(int s) {priority_queue<Point> myPriorityQueue;dis[s] = 0;myPriorityQueue.push(Point(s, dis[s]));while (!myPriorityQueue.empty()){int u = myPriorityQueue.top().number;myPriorityQueue.pop();visit[u] = true;for (int i = 0; i < graph[u].size(); i++){int v = graph[u][i].to;int d = graph[u][i].length;if (!visit[v] && dis[v] > dis[u] + d){dis[v] = dis[u] + d;myPriorityQueue.push(Point(v, dis[v]));}}}return; }int main() {int n, m;while (scanf("%d%d", &n, &m) != EOF){memset(visit, false, sizeof(visit));memset(graph, 0, sizeof(graph));fill(dis, dis + n, INF);while (m--){int from, to, length;scanf("%d%d%d", &from, &to, &length);graph[from].push_back(Edge(to, length));graph[to].push_back(Edge(from, length));}int s, t;scanf("%d%d", &s, &t);Dijkstra(s);if (dis[t] == INF){dis[t] = -1;}printf("%d\n", dis[t]);}return 0; }?
4. 總結
注意一下,上面的代碼處理的是無向圖的最短路徑問題。
考慮一下,如果是有向圖的最短路徑問題如何解決呢?
事實上,只需要簡單改變graph的構造方式即可,即注釋掉
graph[to].push_back(Edge(from, length));之后,本代碼可解決有向圖的最短路徑問題。
?
圖論這個章節難度還是挺大的,筆者看了挺長時間還是不得要領。。
在返校之前盡量把最小生成樹問題也放上來吧。。
?
總結
以上是生活随笔為你收集整理的【数据机构】最短路径之Dijkstra算法(迪克斯特拉算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于SpringBoot点餐小程序的开发
- 下一篇: 股票地址