求图的最短路径问题又分为两个方面:
(1)一个顶点到其余各顶点的最短路径;(本文介绍)
(2)图中每对顶点之间的最短路径。
1、一个顶点到其余个顶点的最短路径
给定一个带权有向图G与源点v,求顶点v到G中其余各顶点的最短路径。(限定不存在权值为负的边)
Dijkstra基本思想:将图中所有顶点分为两个集合S与U。S中包含所有已经找到最短路径的顶点,初始时S中只包含源点v。U中包含未找到最短路径的顶点,初始时包含除源点v以外的其余顶点。之后,每找到一条最短路径v--->k,就将k加入集合S中,直至所有顶点都加入到S中。
Dijkstra算法步骤:
(1)以v为源点,找到v到其余个顶点的距离;
若v--->k之间存在边,则将边<v,k>的权值作为v,k之间的距离;
若v--->之间不存在边,则将边<v,k>之间的距离设为∞;
(2)从U 中选出u,v--->u是距离最小的边,将顶点u加入到S中;
(3)以u为中间节点,更新v到其余各顶点的距离;
(4)重复(2)、(3),直至所有的顶点都以已加入S中。
Dijkstra代码实现:
#include<cstdio>
#define INF 32767
using namespace std;
const int MAXV = 100;
int edges[MAXV][MAXV];
struct MGraph{
int n;
int e;
int edges[MAXV][MAXV];
};
void createMGraph(MGraph &g){
int i,j;
int a,b,w;
scanf("%d%d",&g.n,&g.e);
//初始化
for(i=0;i<g.n;i++)
for(j=0;j<g.n;j++){
if(i==j)
g.edges[i][j] = 0;
else
g.edges[i][j] = INF;
}
for(i=0;i<g.e;i++){
scanf("%d%d%d",&a,&b,&w);
g.edges[a][b] = w;
}
}
void Dispath(MGraph g,int dist[],int path[],int s[],int v){
int i,j,k;
int apath[MAXV],d; //存放一条最短路径(逆向)以及顶点个数
for(i=1;i<=g.n;i++){
if(s[i]!=0 && i!=v){
printf("%d---%d的最短路径为:%d\t路径为",v,i,dist[i]);
d =0;apath[d] = i; //添加路径上的终点
k = path[i];
if(k==-1) //无路径的情况
printf("无路径\n");
else
{
while(k!=v){ //存在路径是输出该路径
d++,apath[d]=k;
k = path[k];
}
d++;apath[d]=v; //添加起点
printf("%d",apath[d]); //先输出起点
for(j=d-1;j>=0;j--) //再输出其他顶点
printf(" ,%d",apath[j]);
printf("\n");
}
}
}
}
void Dijkstra(MGraph g,int v){
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u;
for(i=0;i<g.n;i++){ //步骤(1),初始化dist[],path[],s[]
dist[i] = g.edges[v][i];
s[i] = 0;
if(g.edges[v][i]<INF)
path[i] = v;
else
path[i] = -1;
}
s[v] = 1;path[v] = v;
for(i=0;i<g.n;i++){
mindis = INF;
for(j=0;j<g.n;j++) //步骤(2)遍历边,找到最短的,将顶点u加入S中
if(s[j]==0 && dist[j]<mindis){
u = j;
mindis = dist[j];
}
s[u] = 1;
for(j=0;j<g.n;j++) //步骤(3)以u为中间节点,更新v到U中各点的距离
if(s[j]==0)
if(g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[j]){//如果v--->u--->j的距离小于 v--->j的距离,则更新
dist[j] = dist[u]+g.edges[u][j];
path[j] = u;
}
}
Dispath(g,dist,path,s,v);
}
int main(){
MGraph g;
createMGraph(g);
Dijkstra(g,0);
return 0;
}
/*
7 12
0 1 4
0 2 6
0 3 6
2 4 6
2 5 4
1 4 7
1 2 1
3 2 2
3 5 5
4 6 6
5 4 1
5 6 8
*/
运行结果: