我们在生活中常常遇到最短路问题,比如电力系统和网络带宽的布置,水管与物料传输。这些问题都可以抽象成图论中的最短路问题——我们需要找到最短的路径,达到节约资源的目的。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算法正确的输出了结果。