Dijkstra 算法实现样例
样例输入:
6
0 2 5
0 3 30
1 0 2
1 4 8
2 5 7
2 1 15
4 3 4
5 3 10
5 4 18
-1 -1 -1
样例输出:
20 0->2->1
5 0->2
22 0->2->5->3
28 0->2->1->4
12 0->2->5
#include <stdio.h> #include <string.h> #define INF 1000000 //无穷大 #define MAXN 20 //顶点个数的最大值 int n; //顶点个数 int Edge[MAXN][MAXN]; //邻接矩阵 int S[MAXN]; //Dijkstra算法用到的3个数组 int dist[MAXN]; // int path[MAXN]; // void Dijkstra( int v0 ) //求顶点v0到其他顶点的最短路径 { int i, j, k; //循环变量 for( i=0; i<n; i++ ) { dist[i] = Edge[v0][i]; S[i] = 0; if( i!=v0 && dist[i]<INF ) path[i] = v0; else path[i] = -1; } S[v0] = 1; dist[v0] = 0; //顶点v0加入到顶点集合S for( i=0; i<n-1; i++ ) //从顶点v确定n-1条最短路径 { int min = INF, u = v0; //选择当前集合T中具有最短路径的顶点u for( j=0; j<n; j++ ) { if( !S[j] && dist[j]<min ) { u=j; min = dist[j]; } } S[u] = 1; //将顶点u加入到集合S,表示它的最短路径已求得 for( k=0; k<n; k++ ) //修改T集合中顶点的dist和path数组元素值 { if( !S[k] && Edge[u][k]<INF && dist[u] + Edge[u][k] < dist[k] ) { dist[k] = dist[u] + Edge[u][k]; path[k] = u; } } } } int main( ) { int i, j; //循环变量 int u, v, w; //边的起点和终点及权值 scanf( "%d", &n ); //读入顶点个数n while( 1 ) { scanf( "%d%d%d", &u, &v, &w ); //读入边的起点和终点 if( u==-1 && v==-1 && w==-1 ) break; Edge[u][v] = w; //构造邻接矩阵 } for( i=0; i<n; i++ ) { for( j=0; j<n; j++ ) { if( i==j ) Edge[i][j] = 0; else if( Edge[i][j]==0 ) Edge[i][j] = INF; } } Dijkstra( 0 ); //求顶点0到其他顶点的最短路径 int shortest[MAXN]; //输出最短路径上的各个顶点时存放各个顶点的序号 for( i=1; i<n; i++ ) { printf( "%d\t", dist[i] ); //输出顶点0到顶点i的最短路径长度 //以下代码用于输出顶点0到顶点i的最短路径 memset( shortest, 0, sizeof(shortest) ); int k = 0; //k表示shortest数组中最后一个元素的下标 shortest[k] = i; while( path[ shortest[k] ] != 0 ) { k++; shortest[k] = path[ shortest[k-1] ]; } k++; shortest[k] = 0; for( j=k; j>0; j-- ) printf( "%d→", shortest[j] ); printf( "%d\n", shortest[0] ); } return 0; }
/* Dijkstra O(E * log E) INIT: 调用init(nv, ne)读入边并初始化; CALL: dijkstra(n, src); dist[i]为src到i的最短距离 */ int cost[E], dist[V]; int e, pnt[E], nxt[E], head[V], prev[V], vis[V]; struct qnode { int v; int c; qnode(int vv = 0, int cc = 0) : v(vv), c(cc) {} bool operator<(const qnode & r) const {return c > r.c;} }; void dijkstra(int n, const int src) { qnode mv; int i, j, k, pre; priority_queue<qnode> que; vis[src] = 1; dist[src] = 0; que.push(qnode(src, 0)); for (pre = src, i = 1; i < n; i++) { for (j = head[pre]; j != -1; j = nxt[j]) { k = pnt[j]; if (vis[k] == 0 && dist[pre] + cost[j] < dist[k]) { dist[k] = dist[pre] + cost[j]; que.push(qnode(pnt[j], dist[k])); prev[k] = pre; } } while (!que.empty() && vis[que.top().v] == 1) que.pop(); if (que.empty()) break; mv = que.top(); que.pop(); vis[pre = mv.v] = 1; } } inline void addedge(int u, int v, int c) { pnt[e] = v; cost[e] = c; nxt[e] = head[u]; head[u] = e++; } void init(int nv, int ne) { int i, u, v; int c; e = 0; memset(head, -1, sizeof (head)); memset(vis, 0, sizeof (vis)); memset(prev, -1, sizeof (prev)); for (i = 0; i < nv; i++) dist[i] = inf; for (i = 0; i < ne; ++i) { scanf("%d%d%d", &u, &v, &c); // %d: type of cost addedge(u, v, c); // vertex: 0 ~ n-1, 单向边,双向边时加两次即可 } }