数据结构回顾与总结 图(3)Floyd算法(多源最短路问题)

在现实生活中也会经常碰到多源最短路的问题。比如说供货,我是一个连锁供应商的老板,我们的货从海外运过来,然后选择一个城市作为主要供货城市,别的城市的货源都由该城市提供,要求这个城市去其它城市的运输最便捷,这个城市的选择其实就是一个多源最短路问题。

解决多源最短路问题有两个思路,1是对每个节点使用单源最短路算法(dijkstra什么的),2就是采用floyd算法。这里主要回顾floyd算法。

说实话,在最近一系列的图的练习中,有一点对我来说还是蛮重要的,可能说这点挺白痴的,但还是想说出来。那就是对于邻接矩阵的理解。乍一看邻接矩阵挺好理解的,D[i][j] 不就是表示i点和j点之间的距离么。但是细细想一想,我们经常不经意的把i和j之间连通与D[i][j] 的值为正常值(不是0,-1或者正无穷这样的值)划等号。但其实这是非常错误的,邻接矩阵仅表示“直接”相连的两点之间的关系(连不连通,权重是多少。)

而Floyd其实在一定程度上考察到了这一点,因为对于Floyd算法来说,对于所有K*K范围内的矩阵来说,其实都已经不算是邻接矩阵了,而是直接表示当前遍历程度(用K表示)下两个点之间的最短距离。Floyd通过不断更新邻接矩阵,慢慢将i与j(i与j在0到n-1内随意取值)之间的距离进行改变,最终当K取到n-1时,所有距离更新完毕,这时如果我们想知道某两个点之间的最短距离,直接进行遍历就好了。

说完小坑之后,我们一步步的说一下具体思路。先从整个邻接矩阵D的最小的子矩阵开始,D[0][0] 为1*1矩阵,也是第一个元素,没什么好说的跳过。然后是2*2矩阵,也没什么好说的,因为都是1对1的元素,和邻接矩阵没有区别。到了3*3矩阵就开始有变化了,因为D[i][j] 和D[i][k]+D[k][j] 开始不一定相等,于是我们需要逐个遍历并把D中对应的位置填上两者中的较小值。一直重复整个过程,直到整个矩阵更新完毕。

这是整个算法的python代码,假设图是无权图。

def floyd(n,mat):
    for k in range(n):
        for i in range(n):
            for j in range(n):
                if i==j or i==k or j==k:
                    continue
                pos = get_pos(i,j)
                a = mat[get_pos(i,k)]+mat[get_pos(k,j)]
                b = mat[get_pos(i,j)]
                if a<b:
                    mat[pos] = a
    return mat  

其中调用了一个get_pos(a,b)函数,源码如下:

def get_pos(a,b):
    if a>=b:
        return int(b+a*(a+1)/2)
    else:
        return int(a+b*(b+1)/2)

很容易看到,这个算法的时间复杂度是O(n^3)可以说复杂度是比较高的了,所以我用python做oj上的题老是超时!!!!!烦躁。

真的该严肃考虑一下是否要把cpp这种语言搞一下了,不然真的太烦了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值