单源点的最短路径问题:给定带权有向图G和源点V,求从V到G中其余各顶点的最短路径
Dijkstra算法描述如下:
(1)用带权的邻接矩阵arcs表示有向图,arcs[i][j]表示弧<vi,vj>上的权值,若<vi,vj>不存在,则置arcs[i][j]=INF。
vis为已找到从v出发的最短路径的终点集合,它的初始状态为空集。那么,从v出发到图上其余各顶点可能到达的最短路径初值为:
D[i]=arcs[Vex(G,v)][i],vi属于V
(2)选择vj,使得D[j]=Min{D[i]|vi属于V-vis},vj就是当前求得的一条从v出发的最短路径的终点。令vis=vis U {j}
(3)修改从v出发到集合V-vis上任一顶点vk可达的最短路径长度。如果D[j]+arcs[j][k]<D[k],则修改D[k]=D[j]+arcs[j][k]
(4)重复操作(2)、(3)工n-1次。由此求得从v到图上其余各顶点的最短路径是依路径长度递增的序列
//Dijkstra:从某个源点到其余各顶点的最短路径 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #define N 500 #define INF 0x3f3f3f3f //1061109567 -- 3*(16^7+16^5+16^3+16)+15*(16^6+16^4+16^2+1) bool vis[N];//顶点是否已经选入S int p[N];//前驱顶点 int dis[N];//最短路径 typedef struct graph{ int vexnum;//顶点数 int edgenum;//边数 int arc[N][N];//邻接矩阵 }Graph; void CreateGraph(Graph* &); void Dijkstra(Graph*); void sp(int,int);//最短路 void CreateGraph(Graph* &G) { int i,v,w; memset(G->arc,INF,sizeof(G->arc));//初始化为INF //printf("%d",G->arc[100][100]); printf("有向图的顶点数和边数:"); scanf("%d%d",&G->vexnum,&G->edgenum); printf("有向图顶点序号以及关联权值:"); for(i=0;i<G->edgenum;i++) { scanf("%d%d",&v,&w); scanf("%d",&G->arc[v][w]); } } void Dijkstra(Graph *G) { int i,v,w,min; memset(vis,false,sizeof(vis)); memset(p,0,G->vexnum);//初始时所有终点的前驱顶点都为始点0 for(i=1;i<G->vexnum;i++)//最短路径初始化为始点到终点的直接路径长度 dis[i] = G->arc[0][i]; for(i=1;i<G->vexnum;i++)//进行G->vexnum-1次循环,按路径递增每次确定一个顶点 { min = INF; for(w=1;w<G->vexnum;w++) { if(!vis[w] && dis[w] <= min)//此处取=号是确保输出 路径时能够显示No Path的顶点 { v = w;//v保存当前最小路径对应的终点 min = dis[w]; } } vis[v] = true; sp(v,min);//显示最短路径以及长度 for(w=1;w<G->vexnum;w++)//更新当前最短路径以及距离 { if(!vis[w] && min + G->arc[v][w] < dis[w]) { dis[w] = min + G->arc[v][w]; p[w] = v; } } } } void sp(int v,int pow) { if(pow == INF) { printf("V0--->V%d:No Path ",v); } else{ printf("V0-->V%d最短路径长度为:%d,路径如下: ",v,pow); while(v)//从后往前打印,到始点0结束 { printf("V%d<-",v); v = p[v]; } printf("V0 "); } } int main() { Graph *G = (Graph *)malloc(sizeof(Graph)); CreateGraph(G); Dijkstra(G); return 0; } // 6 8 // 0 2 10 // 0 4 30 // 0 5 100 // 4 5 60 // 4 3 20 // 3 5 10 // 2 3 50 // 1 2 5