其他分享
首页 > 其他分享> > 最短路径问题

最短路径问题

作者:互联网

Floyd(弗洛伊德)算法

Floyed算法(时间复杂度为O(N3),空间复杂度为O(N2)),是解决任意两点间的最短路径的一种算法,可以正确处理有向图负权的最短路径问题。

引例:

暑假,小哼准备去一些城市旅游。有些城市之间有公路,有些城市之间则没有,如下图。为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程。

上图中有4个城市8条公路,公路上的数字表示这条公路的长短。请注意这些公路是单向的。我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径。这个问题这也被称为“多源最短路径”问题。

我们可以用一个4*4的矩阵(二维数组e)来存储图的信息。比如:

具体如下

如果要让任意两点(例如从顶点a点到顶点b)之间的路程变短,只能引入第三个点(顶点k),并通过这个顶点k中转即a->k->b,才可能缩短原来从顶点a点到顶点b的路程。当然这个中转的顶点有时候甚至不止一个,即a->k1->k2b->或者a->k1->k2…->k->i…->b。比如上图中从4号城市到3号城市(4->3)的路程e[4][3]原本是12。如果只通过1号城市中转(4->1->3),路程将缩短为11(e[4][1]+e[1][3]=5+6=11)。其实1号城市到3号城市也可以通过2号城市中转,使得1号到3号城市的路程缩短为5(e[1][2]+e[2][3]=2+3=5)。所以如果同时经过1号和2号两个城市中转的话,从4号城市到3号城市的路程会进一步缩短为10。

因此,我们可以遍历每一个点作为中间点k,然后计算最小值

for (k = 1; k <= n; k++)
    for (i = 1; i <= n; i++)
        for (j = 1; j <= n; j++)
            if (e[i][j] > e[i][k] + e[k][j])
                e[i][j] = e[i][k] + e[k][j];

也许有的人会有疑问,这样的遍历只遍历了中间点个数为1的情况,没有考虑中间点个数大于等于1的情况。其实不然,在计算中间点为k的最小值的时候,把能更新的元素都更新了,比如说更新了e[i][j],这时候矩阵中第i行第j列的元素实际上是e[i][k]+e[k][j],而不是e[i][j]了。这边用到了动态规划的思想。

总结下Floyed算法:

算法核心:每次引入一个点k来更新i到j最短距离,求出任意两点之间的最短距离。

基本步骤如下:

  1. 从任意一条单边路径开始,所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
  2. 对于每一对顶点u和v,看看是否存在一个顶点w使得从u到w再到v比己知的路径更短,如果是更新它。
  3. 对于所有的顶点,都重复上面的操作,直到遍历所有的顶点。

 

标签:路程,中转,城市,路径,最短,问题,顶点,任意
来源: https://www.cnblogs.com/stu-jyj3621/p/12924651.html