关于floyd-warshall算法的一个疑问

march_on 2011-11-03 09:49:18
按照《算法导论》上的递归公式,令dij(k)为从顶点i到顶点j,且满足所有中间顶点皆属于集合{1,2,…,k}的一条最短路径的权值。当k=0时,表示i和j之间的路径上没有编号大于0的中间节点,即不存在中间节点。所以dij(0) = wij.根据以上讨论,递归式如下:
wij k=0
dij(k) = {
min( dij(k-1), dik(k-1)+dkj(k-1) ) k>=1

我的疑问如下:
以计算dij(4)为例,假设我们已经计算完了d4 2(2)且d4 2(2)不同于d4 2(1),那么在计算d4 3(2)时,我们会用到d4 2(1)和d2 2(1),但是此时d4 2 (1)已经被更新成d4 2(2)了,我们在实现的时候是不是应该保存d4 2(1)呢?
但是在《算法导论》给出的实现里面(P387)并没有在计算dij(k)前保存dij(k-1)。

我的意思是计算dij(k)时要用到dik(k-1)和dkj(k-1),但是dik(k-1)、dkj(k-1)可能在之前计算的时候已经被更新成dik(k)和dkj(k)了。那么我们实现的时候应该在计算dij(k)前先保存dij(k-1),否则程序就是错的了,至少没有按照之前定义的递归式进行计算。

我想我应该表述的比较清晰了,请大家帮忙看一看,谢了。
d4 2 (2)表示从顶点4到顶点2的且中间节点属于{1,2}的一条最短路径,其余类推。
...全文
183 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
FancyMouse 2011-11-04
  • 打赏
  • 举报
回复
>那么怎么知道这样实现得到的还是正确的结果呢?
仔细理解这句:“最外层的for(k=0;k<n;k++)以后d[i][j]存储的是i->j经过0,1,...,k中间节点的最短路径,而不是长度为k的最短路径。”。用归纳法证出这句以后,外层for结束以后d就是要求的数组。

>如果没有保存dij(k-1),那么递推公式里面使用的dik(k-1)或dkj(k-1)可能就是被更新过的了,那它就是dik(k)或dkj(k)
所以3次方时间的那个d和这个d^k/d^(k-1)根本没关系。意义上就不一样。唯一的共同点是递推式一样(但是递推顺序不一样)。
FancyMouse 2011-11-03
  • 打赏
  • 举报
回复
保存k-1这个数组的话那就是3次方的空间4次方的时间了。我们平时的2次方空间3次方时间的写法是用了这个递推式但不是严格采用递推式的递推顺序。在3次方时间的写法下,最外层的for(k=0;k<n;k++)以后d[i][j]存储的是i->j经过0,1,...,k中间节点的最短路径,而不是长度为k的最短路径。
march_on 2011-11-03
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 fancymouse 的回复:]

保存k-1这个数组的话那就是3次方的空间4次方的时间了。我们平时的2次方空间3次方时间的写法是用了这个递推式但不是严格采用递推式的递推顺序。在3次方时间的写法下,最外层的for(k=0;k<n;k++)以后d[i][j]存储的是i->j经过0,1,...,k中间节点的最短路径,而不是长度为k的最短路径。
[/Quote]
先谢谢你的回答。你说的我有两点不太明白:
如果平时的2次方空间3次方时间的写法是用了递推式但又不是严格采用递推式的递推顺序,那么怎么知道这样实现得到的还是正确的结果呢?
另外一条,就是你说的最后一句,“在3次方时间的写法下,最外层的for(k=0;k<n;k++)以后d[i][j]存储的是i->j经过0,1,...,k中间节点的最短路径,而不是长度为k的最短路径。”如果没有保存dij(k-1),那么递推公式里面使用的dik(k-1)或dkj(k-1)可能就是被更新过的了,那它就是dik(k)或dkj(k),那么第k次循环得到的d[i][j]存储的还是经过0,1,…,k中间节点的最短路径吗?

33,010

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧