我正在阅读关于数据结构中的所有对最短路径算法和Wessis书中的算法分析
如下面的伪C代码所示,当k> 0我们可以写一个简单的 Dk,i,j的公式。从vi到vj的最短路径,仅使用v1, v2 ,. 。 。 ,作为中间体的vk是最短的路径 不要使用vk作为中间体,或者包含合并 两条路径vi vk和vk vj,每条路径仅使用第一个k - 1个顶点作为中间体。这导致公式
Dk,i,j = min {Dk - 1,i,j,Dk - 1,i,k + Dk - 1,k,j}
时间要求再次为O(| V | 3)。因为第k阶段 仅取决于(k-1)st阶段,它似乎只有两个| V | X | V |需要维护矩阵。但是,使用k作为 用k开始或结束的路径上的中间顶点不会 除非存在负循环,否则改善结果。因此,只有一个 矩阵是必要的,因为Dk-1,i,k = Dk,i,k和Dk-1,k,j = Dk,k,j, 这意味着右边的任何条款都没有改变价值和 需要得救。
我的问题:
作者的意思是“然而,使用k作为以k开头或结尾的路径上的中间顶点不会改善结果,除非 有一个负面的循环“?
作者如何得出“Dk-1,i,k = Dk,i,k和Dk-1,k,j = Dk,k,j”?
任何人都可以用简单的例子解释
/* Compute All-Shortest Paths */
/* A[] contains the adjacency matrix */
/* with A[i][i] presumed to be zero */
/* D[] contains the values of shortest path */
/* |V | is the number of vertices */
/* A negative cycle exists iff */
/* d[i][j] is set to a negative value at line 9 */
/* Actual Path can be computed via another procedure using path */
/* All arrays are indexed starting at 0 */
void
all_pairs( two_d_array A, two_d_array D, two_d_array path )
{
int i, j, k;
/*1*/ for( i = 0; i < |V |; i++ ) /* Initialize D and path */
/*2*/ for( j = 0; j < |V |; j++ )
{
/*3*/ D[i][j] = A[i][j];
/*4*/ path[i][j] = NOT_A_VERTEX;
}
/*5*/ for( k = 0; k < |v |; k++ )
/* Consider each vertex as an intermediate */
/*6*/ for( i = 0; i < |V |; i++ )
/*7*/ for( j = 0; j < |V |; j++ )
/*8*/ if( d[i][k] + d[k][j] < d[i][j] )
/*update min */
{
/*9*/ d[i][j] = d[i][k] + d[k][j];
/*10*/ path[i][j] = k;
}
}
答案 0 :(得分:2)
以下是您问题的答案。
1)Floyd算法利用动态规划递推方程来确定顶点之间的所有对最短路径;重复是基于以下事实:为了找到几个顶点 i 和 j 之间的最短路径,你必须检查是否直接从 i < / em>到 j 比从 i 到中间顶点 k 然后从 k 更便宜Ĵ。您检查所有顶点 i , j 和 k ,以便复杂度为O( n ^ 3 )。现在考虑一下:如果所有权重都是非负的,那么最短路径的概念就很明确了。相反,如果存在负循环,这个概念就没有意义了。为什么?因为如果在从顶点 i 到顶点 j 的路径上发现负循环,那么您可以根据需要遍历循环次数,并且每次都可以遍历循环,相应路径的成本降低,因为属于循环的边缘上的权重是负的。因此,负循环显然会改善最短路径的成本(成本降低)。因此,如果允许边缘上的负权重,则能够检测负循环非常重要。 Floyd算法假设边缘为正,但能够检测到负循环。
2)递归方程式如下,略微简化了您的符号:
d[i, j] <- min(d[i, j], d[i, k] + d[k, j])
实际使用它如下面的伪代码
所示for k <- 0 to n-1
for i<- 0 to n-1
for j <- 0 to n-1
d[i, j] <- min(d[i, j], d[i, k] + d[k, j])
d [i,j]的每次更新都需要访问d [i,k]和d [k,j],因此作者要问:如果更新d [i,j]需要值d [i,k] ]和d [k,j]我们如何确定在 k -th迭代期间已经计算了这些值?我们如何确保在 k -th迭代期间这些值不会发生变化?
实际上,这些值在 k -th迭代期间不能改变,因此没有功能依赖性。这就是原因。实际上,在迭代 k 期间,对d [i,k]的更新采用
形式d[i, k] <- min(d[i, k], d[i, k] + d[k, k])
但是d [k,k]为零,因此d [i,k]不会改变。
同样,d [k,j]的更新是
d[k, j] <- min(d[k, j], d[k, k] + d[k, j])
这样d [k,j]也不会改变。