美文网首页
turtle Floyd-Warshall(Graph)

turtle Floyd-Warshall(Graph)

作者: Python_Camp | 来源:发表于2022-04-10 11:15 被阅读0次
import turtle
turtle.speed(0)
size=1
while size < 500:
  turtle.forward(size)
  turtle.right(1000)
  size = size + 1
turtle.done()

最短路径算法

Floyd-Warshall(打开新窗口)的算法是用来寻找具有正负边权重的加权图中的最短路径。该算法的一次执行就能找到所有对顶点之间最短路径的长度(权重之和)。只要稍加改动,它就能打印出最短路径,并能检测出图中的负循环。Floyd-Warshall是一种动态编程算法。

让我们看一个例子。我们将在这个图上应用Floyd-Warshall的算法:图例

image.png

我们做的第一件事是,我们取两个二维矩阵。这些是邻接矩阵(打开新窗口)

矩阵的大小将是顶点的总数。对于我们的图形,我们将采取4*4矩阵。距离矩阵将存储迄今为止在两个顶点之间发现的最小距离。

首先,对于边,如果u-v之间有一条边,并且距离/权重是w,我们将存储:distance[u][v] = w。对于所有不存在的边,我们将输入无穷大。

路径矩阵是为了重新生成两个顶点之间的最小距离路径。因此,最初,如果u和v之间有一条路径,我们就把path[u][v]=u放进去。这意味着从顶点u到达顶点v的最佳方式是使用连接v和u的边。我们的图的两个表将看起来像。

因为没有循环,所以对角线设为N,而与顶点本身的距离为0。

为了应用Floyd-Warshall算法,我们要选择一个中间的顶点k。然后对于每个顶点i,我们要检查是否可以从i到k,再从k到j,其中j是另一个顶点,并使从i到j的成本最小化。

如果当前距离[i][j]大于距离[i][k]+距离[k][j],我们要把距离[i][j]等同于这两个距离的总和。

而path[i][j]将被设置为path[k][j],因为最好是从i到k,然后再从k到j,所有顶点将被选为k。 我们将有3个嵌套循环:对于k从1到4,i从1到4,j从1到4。

if distance[i][j] > distance[i][k] + distance[k][j]
    distance[i][j] := distance[i][k] + distance[k][j]
    path[i][j] := path[k][j]
end if

所以我们基本上要检查的是,对于每一对顶点,我们是否通过另一个顶点获得更短的距离?我们的图的总操作数将是444=64。这意味着我们要做64次这样的检查。让我们看一下其中的几个。

当k=1,i=2,j=3时,distance[i][j]为-2,不大于distance[i][k]+distance[k][j]=-2+0=-2。 所以它将保持不变。

同样,当k=1,i=4,j=2时,distance[i][j]=无穷大,这大于distance[i][k]+distance[k][j]=1+3=4。所以我们把distance[i][j]=4,并把path[i][j]=path[k][j]=1。

这意味着,从顶点4到顶点2,路径4->1->2比现有路径短。这就是我们填充两个矩阵的方法。这里显示了每一步的计算过程(打开新窗口)。进行必要的修改后,我们的矩阵将看起来像。

image.png

这就是我们的最短距离矩阵。例如,从1到4的最短距离是3,从4到3的最短距离是2。 我们的伪代码将是。

Procedure Floyd-Warshall(Graph):
for k from 1 to V     // V denotes the number of vertex
    for i from 1 to V
       for j from 1 to V
           if distance[i][j] > distance[i][k] + distance[k][j]
               distance[i][j] := distance[i][k] + distance[k][j]
               path[i][j] := path[k][j]
           end if
       end for
    end for
end for

输出路径:

为了打印路径,我们将检查路径矩阵。为了打印从u到v的路径,我们将从path[u][v]开始。我们将不断改变v=path[u][v],直到找到path[u][v]=u,并将path[u][v]的每个值推到堆栈中。找到u后,我们将打印u,并开始从堆栈中弹出项目并打印它们。这是因为路径矩阵存储了从任何其他节点到v的最短路径的顶点的值。伪代码将是。

Procedure PrintPath(source, destination):
s = Stack()
S.push(destination)
while Path[source][destination] is not equal to source
    S.push(Path[source][destination])
    destination := Path[source][destination]
end while
print -> source
while S is not empty
    print -> S.pop
end while

寻找负的边缘循环

为了找出是否有一个负的边缘循环,我们需要检查距离矩阵的主对角线。如果对角线上的任何数值是负的,那就意味着图中有一个负的循环。

复杂度

Floyd-Warshall算法的复杂度为O(V³),空间复杂度为。O(V²)。

相关文章

网友评论

      本文标题:turtle Floyd-Warshall(Graph)

      本文链接:https://www.haomeiwen.com/subject/ukrvsrtx.html