1. 程式人生 > >C++實現最短路演算法——Dijkstra演算法

C++實現最短路演算法——Dijkstra演算法

我們在生活中常常遇到最短路問題,比如電力系統和網路頻寬的佈置,水管與物料傳輸。這些問題都可以抽象成圖論中的最短路問題——我們需要找到最短的路徑,達到節約資源的目的。Dijkstra演算法可以用於解決有向圖中,所有權值為正的情況下,單源最短路問題。它可以實現計算有向圖中一個點到所有點的最小路徑。

下面的程式碼實現了這個演算法,使用鄰接表儲存圖,並封裝到結構體中用於計算,便於使用:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#define FOR(x,f,t) for(x=f;x<=t;++x) #define RFOR(x,f,t) for(x=f;x>=t;--x) #define oo 2147483647 #define M 505 #define MEMSET(a,b) memset(a,b,sizeof(a)); typedef long long ll; using namespace std; struct DD { int id,dist; DD(int i,int d):id(i),dist(d) {} bool operator < (const DD& dd) const
{ //按每點D值排序,用於下面的優先佇列 return dist>dd.dist; } }; struct Edge { int f,t,len; Edge(int a,int b,int c):f(a),t(b),len(c) {} }; struct Dijkstra { int size; bool taken[M]; int d[M]; vector<Edge> edges; void init(int size) { this->size=size; edges.clear(); } void
addEdge(int f,int t,int len) { edges.push_back(Edge(f,t,len)); } void dijkstra(int s) { MEMSET(taken,0); //清空標記 MEMSET(d,127); //將每點d值填充到無窮大 d[s]=0; //起始點d值為0 priority_queue<DD> Q; Q.push(DD(s,0)); int i; while(!Q.empty()) { DD mi=Q.top(); //取出剩餘點中d值最小的點 Q.pop(); int x=mi.id; taken[x]=true; FOR(i,0,edges.size()-1) { Edge& e=edges[i]; if (taken[e.t]) continue; if (e.f!=x) continue; d[e.t]=min(d[e.t],d[x]+e.len); Q.push(DD(e.t,d[e.t])); } } } }; int main() { Dijkstra d; int i,n,m; cin>>n>>m; //圖一共有n個點,m條邊 d.init(n); //初始化 FOR(i,1,m) { int a,b,c; cin>>a>>b>>c; d.addEdge(a,b,c); //新增邊 } d.dijkstra(1); //求從第1個點開始到所有點的距離 FOR(i,1,n) cout<<d.d[i]<<" "; return 0; }

測試輸入:

5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60

輸出:

0 10 50 30 60

可以看到,Dijkstra演算法正確的輸出了結果。