最短路floyd与dijkstra浅析

为了备战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值的过程用堆(优先队列)实现,感兴趣的同学可以继续关注我下一篇博客,靴靴~~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值