Dijkstra算法(单源点路径算法)
要求:图中不存在负权值边)
算法步骤如下:
G={V,E}
- 初始时令
S
=
V
0
,
T
=
V
−
S
=
S={V0},T=V-S=
S=V0,T=V−S={其余顶点},T中顶点对应的距离值
若存在 < V 0 , V i > , d ( V 0 , V i ) <V0,Vi>,d(V0,Vi) <V0,Vi>,d(V0,Vi)为 < V 0 , V i > <V0,Vi> <V0,Vi>弧上的权值
若不存在 < V 0 , V i > <V0,Vi> <V0,Vi>, d ( V 0 , V i ) d(V0,Vi) d(V0,Vi)为 ∞ ∞ ∞
2.若存在 < V 0 , V i > = d ( V 0 , V i ) <V0,Vi>=d(V0,Vi) <V0,Vi>=d(V0,Vi)那么 < V i , V 0 > = d ( V 0 , V i ) <Vi,V0>=d(V0,Vi) <Vi,V0>=d(V0,Vi)(无向图)
注:有向图不需要这一步。 - 从T中选取一个与S中顶点有关联边且权值最小的顶点W,加入到S中
- 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值
重复上述步骤2、3,直到S 中包含所有顶点,即 W = V i W=Vi W=Vi为止
代码实现:
#include<stdio.h>
#define SIZE 110
#define INF 10000000
int dijkstra(int from, int to,int map[SIZE][SIZE],int n,int m){ //从源点到目标点
int i,j;
int START =from;
int parent[SIZE];
int len[SIZE]; //d[i]表示源点到i这个点的距离
int visit[SIZE]; //节点是否被访问
for(int i =0;i<SIZE;i++)
parent[i]=START;
for(i = 1 ; i <= n ; i ++){ //初始化
visit[i] = 0; //一开始每个点都没被访问
len[i] = map[from][i]; //先假设源点到其他点的距离
}
for(i = 1 ; i <= n ; ++i){ //对除源点的每一个点进行最短计算
int min = INF; //记录最小len[i]
int pos; //记录小len[i] 的点
for(j = 1 ; j <= n ; ++j)
{
if(!visit[j] && min > len[j]){
pos = j;
min = len[j];
}
}
visit[pos] = 1;
for(j = 1 ; j <= n ; ++j){
if(!visit[j] && (len[j] > (len[pos] +map[pos][j])))
{ //如果j节点没有被访问过&&j节点到源节点的最短路径>pos节点到源节点的最短路径+pos节点到j节点的路径
len[j] = len[pos] + map[pos][j]; //更新j节点到源节点的最短路径
parent[j]=pos; //记录前驱结点
}
}
}
for(i=1;i<=n;i++)
{
if(i!=from)
printf("the parent of %d is %d \n",i,parent[i]);
}
return len[to];
}
void gen(int map[SIZE][SIZE],int vertex_num,int edge_num)
{
int i,j;
int k;
int Ver;
int start,end;
for(i=0;i<=vertex_num;i++)
{
for(j=0;j<=vertex_num;j++)
map[i][j] = INF;
}
for(k=0;k<edge_num;k++)
{
scanf("%d%d",&i,&j);
scanf("%d",&map[i][j]);
map[j][i] = map[i][j];
}
}
int main () {
int map[SIZE][SIZE];
int vertex_num;
int edge_num;
int start,end;
scanf("%d%d",&start,&end);
scanf("%d%d",&vertex_num,&edge_num);
gen(map,vertex_num,edge_num);
int ans = dijkstra(start,end,map,vertex_num,edge_num);
printf("ans = %d",ans);
return 0;
}
测试数据:
输入:
1 5//求从1到5的最短路径
6 9//六个顶点,九条边
1 2 7
1 3 9
1 6 14
2 3 10
2 4 15
5 6 9
3 6 2
4 5 6
3 4 11
后九行相当于
map[1][2] = 7; //测试数据
map[1][3] = 9;
map[1][6] = 14;
map[2][3] = 10;
map[2][4] = 15;
map[3][6] = 2;
map[5][6] = 9;
map[4][5] = 6;
map[3][4] = 11;
输出:
the parent of 2 is 1
the parent of 3 is 1
the parent of 4 is 3
the parent of 5 is 6
the parent of 6 is 3
shortest path = 20