最短路之~迪科斯彻算法
迪科斯彻算法是由荷兰计算机科学家艾滋郝尔·戴克斯拉提出的。本算法使用广度优先搜索解决非负权有向图的单源最短路径问题。算法终于得到一个最短路径树。此算法经常使用于路由算法或者作为其它图算法一个子模块。本算法是用来找一个点到其它全部点之间的最短路径。
此算法中变量的使用:
map[][]二维数组记录两点之间的权值,比如map[i][j]存放i点到j点的权值。当作为有向图时,给出i,j须要存放的仅仅有一个map[][],但普通情况下都是用无向图,需存两个map[][],即map[i][j]=map[j][i]=权值。
dis[]一维数组存放各点到起点的最短距离。mark[]一维数组标记使用过的点。
单源最短路:
Ⅰ、从一个点出发到其它全部点的最短路径的长度
Ⅱ、基本操作:松弛操作。
Ⅲ、dis[j] > dis[vir] + map[vir][j]这种边(vir,j)成为紧的,能够对它进行松弛操作。
对全部点进行松弛操作的代码可參考:
for(int j = 1; j <= n; j++)
{
if(dis[j] > dis[vir] + map[vir][j] && !mark[j])
dis[j] = dis[vir] + map[vir][j];
}
Ⅳ、最開始给每个点一个非常大的dis值,从dis[s] = 0;開始,不断给能够松弛的点进行松弛操作。直至求出全部点的最短路径。
本算法要求图中不存在负权边。
可证明:具有最小的dis[i]的点没有增加最短路时,此后的点无法松弛。所以每次均要寻找近期的点进行松弛操作。
详细请參考代码:
#include<stdio.h>
#define INF 0x3f3f3f3f //定义一个较大的值。用来初始化
int map[1010][1010]; //存放两点间的权值
int dis[1010]; //存放各点距起点的距离
int mark[1010]; //标记使用过的点
int n,m; //有n个点,编号为1~n,有m组数据
void dijkstra(int s)
{
int vir,min;
for(int i=1;i<=n;i++) //初始化标记数组和距离数组
{
mark[i]=0; //0表示未使用此点
dis[i]=INF;
}
dis[s]=0;
for(int i=1;i<=n;i++)
{
min=INF;
for(int j=1;j<=n;j++) //查找权值最小的点
{
if(!mark[j]&&dis[j]<min)
{
min=dis[j];
vir=j;
}
}
if(min==INF) break; //若没查找到或已查找完成。跳出
mark[vir]=1; //将查找到的点标记
for(int j=1;j<=n;j++) //将未查找到并可松弛的点进行松弛操作
{
if(!mark[j]&&dis[j]>dis[vir]+map[vir][j])
dis[j]=dis[vir]+map[vir][j];
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++) //初始化map数组
for(int j=1;j<=n;j++)
map[i][j]=INF;
for(int i=0;i<m;i++)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d); //输入两点及权值
if(map[x][y]>d) //若有反复。取较短的
{
map[x][y]=d;
map[y][x]=d;
}
}
int start,end;
scanf("%d%d",&start,&end); //输入起点和终点
dijkstra(start); //调用迪科斯彻算法
printf("%d
",dis[end]); //输出起点与终点间最短距离
}
return 0;
}