维基说的很全面:https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
理解:
先设置访问数组vis[]和距离数组dist[],开始时把源点(source)先加入已访问数组(vis[source]=1),源点到源点的距离数组设为0(dist[source]=0);然后其它点到源点的dist[]为源点到该点的距离。然后找与源点相连的最近的点,并将其加入访问数组,再用这个点利用松弛操作更新其它未访问的点。循环执行顶点数-1次结束。
下面代码假设源点为1,终点为N。
#include<iostream> #include<cstring> #include<cstdio> #include<vector> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 2000; int matrix[maxn][maxn]; int vis[maxn], dist[maxn]; int N, M; void Dijkstra(int source) { memset(vis, 0, sizeof(vis)); vis[source] = 1; for (int i = 1; i <= N; i++) dist[i] = matrix[source][i]; int cost, k; for (int i = 1; i < N; i++) { cost = INF; for (int j = 0; j <= N; j++) { if (!vis[j] && dist[j]<cost) { cost = dist[j]; k = j; } } vis[k] = 1; for (int j = 0; j <= N; j++) { if (!vis[j] && matrix[k][j] != INF&&dist[j]>matrix[k][j] + cost) { dist[j] = matrix[k][j] + cost; } } } } int main() { while (scanf("%d%d", &N, &M)) { for (int i = 0; i <= N; i++) for (int j = 0; j <= N; j++) if (i == j) matrix[i][j] = 0; else matrix[i][j] = INF; for (int i = 0; i<M; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); matrix[u][v] = matrix[v][u] = w; } Dijkstra(1); printf("%d\n", dist[N]); } return 0; }
用优先队列和vector:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int INF=0x3f3f3f3f; const int maxn=2000; struct Node { int num,dis;//num存储当前节点的编号,dis存储路径长度 Node(){} Node(int a,int b){num=a;dis=b;} bool operator < (const Node& rhs)const{ dis>rhs.dis; } }; priority_queue<Node>que; vector<vector<Node> >v; int vis[maxn],dist[maxn]; int N,M; void Dijkstra(int s) { for (int i=0;i<=N;i++) dist[i]=INF; dist[s]=0; que.push(Node(s,dist[s])); while(!que.empty()) { Node p=que.top();que.pop(); for (int i=0;i<v[p.num].size();i++) { Node q; q.num=v[p.num][i].num; if(dist[q.num]>dist[p.num]+v[p.num][i].dis) { dist[q.num]=dist[p.num]+v[p.num][i].dis; que.push(Node(q.num,dist[q.num])); } } } } int main() { scanf("%d%d",&N,&M); v.clear(); v.resize(N+1); for (int i=0;i<M;i++) { int fr,to,w; scanf("%d%d%d",&fr,&to,&w); v[fr].push_back(Node(to,w)); v[to].push_back(Node(fr,w)); } Dijkstra(1); printf("%d\n",dist[N]); }
以hdu1874畅通工程续为例,一个pair较为偷懒的写法:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int maxn = 1005; 7 vector<pair<int, int> > E[maxn]; 8 int d[maxn]; 9 int n, m; 10 11 void Dijkstra(int s) 12 { 13 priority_queue<pair<int, int> >Q; 14 d[s] = 0; 15 Q.push(make_pair(-d[s],s)); 16 while (!Q.empty()) 17 { 18 int now = Q.top().second; Q.pop(); 19 for (int i = 0; i < E[now].size(); i++) 20 { 21 int v = E[now][i].first; 22 if (d[v] > d[now] + E[now][i].second) 23 { 24 d[v] = d[now] + E[now][i].second; 25 Q.push(make_pair(-d[v], v)); 26 } 27 } 28 } 29 } 30 31 int main() 32 { 33 while (scanf("%d%d",&n,&m)==2) 34 { 35 for (int i = 0; i < n; i++) E[i].clear(); 36 for (int i = 0; i < n; i++) d[i] = 1e9; 37 for (int i = 0; i < m; i++) 38 { 39 int x, y, z; 40 scanf("%d%d%d", &x, &y, &z); 41 E[x].push_back(make_pair(y,z)); 42 E[y].push_back(make_pair(x, z)); 43 } 44 int s, t; 45 scanf("%d%d", &s, &t); 46 Dijkstra(s); 47 if (d[t] == 1e9) 48 printf("-1\n"); 49 else 50 printf("%d\n", d[t]); 51 } 52 return 0; 53 }