最短路floyd与dijkstra浅析

来源:互联网 发布:尖头高跟鞋淘宝 编辑:程序博客网 时间:2024/05/20 05:28

为了备战noip,又将图论的基础知识拿出来练了练。
因为本文主要对象为初级选手,已简单易懂为宗旨,高级大犇不要喷。。靴靴。。。
首先,

floyd算法:此算法是最短路最朴素的办法,用记忆化搜索的思想,枚举起步点(i),转折点(k),终点(j),三重循环,完成最短路,时间复杂度为o(n^3)。因为方法较为暴力,所以编程复杂度较低。下面贴上程序段

for (i=1;i<=n;++i)//起点  for (j=1;j<=n;++j)//终点  if (i!=j)//起点与终点不能重复   for (k=1;k<=n;++k)//转折点   if (i!=k&&j!=k){//点之间不能重复     f[i][j]=min(f[i][j],f[i][k]+f[k][j])//判断for循环构造出的路径是否更优   }

注意for循环之前要将f数组初始化为maxint(f[i][j]下标i==j的话初始化为0);
读程序后,大家也许会发现,floyd似乎不止求出了起点到终点的最短路,而是任意两点之间的最短路,如果仅仅为了求两点之间的最短路就显得过于臃肿。下面我们介绍另一种最短路算法“dijkstra算法”。

dijkstra算法:我个人理解为floyd的一种优化版,运用一个dis数组存放起点到其余任意一个点的已知(就是已经算出来的,不是最后结果)最短路长度。省去了枚举开头着个部分(这就是dijkstra只求两点之间的最短路的原因了)确定了起点,这样就只需要枚举转折点和终点了。大家仔细想想,dis中存放起点到任意一个点的当前距离,其中最短dis[i]的一定是正确的起点到i点的最短路径。因为最短,所以没有经过其他的点(或没有经历过其他的点的i已全部做完,当前点i也一定是最短路径),这样我们找n-1次(第一个不需要找,因为是起点)最小的dis[i](每次不能重复,用一个book数组记录,没找过为0,找过为1),在枚举一个1~n的j,这样起点到j的距离就为min(dis[j],dis[i]+map[i][j]);因为只枚举起点与终点,所以时间复杂度为o(n^2);主代码如下:

for (i=1;i<=n;++i){    dis[i]=map[1][i];//初始化dis数组,dis[i]为1到i的当前最短距离     book[i]=0;//初始化book数组 }book[1]=1;//起点不要枚举 for (i=1;i<=n-1;++i){    for (j=1;j>=n;++j){//查找最小dis值         if (minj>dis[j] && book[j]==0){            minj=dis[j];            u=j;        }    }    book[u]=1;    for (j=1;j<=n;++j){        if (dis[j]>dis[u]+map[u][j]){            dis[j]=dis[u]+map[u][j];//替换更优的解         }    }}

基本的思路就是这样,当然,学习是永无止境的,比如说dijkstra还有许多的优化方法,如:把邻接矩阵改为邻接表,又比如把查找最小dis值的过程用堆(优先队列)实现,感兴趣的同学可以继续关注我下一篇博客,靴靴~~~~

0 1