C++實現最短路演算法——Dijkstra演算法
阿新 • • 發佈:2018-12-24
我們在生活中常常遇到最短路問題,比如電力系統和網路頻寬的佈置,水管與物料傳輸。這些問題都可以抽象成圖論中的最短路問題——我們需要找到最短的路徑,達到節約資源的目的。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演算法正確的輸出了結果。