Floyd(弗洛伊德)算法前言:以图形化的方式呈现问题

Floyd算法--简单易懂版_i++   Floyd算法--简单易懂版_图形化_02

 思路:

1.以矩阵的结构来存储图的信息,本身点间的距离为0,两点间无直达路径距离为∞

            Floyd算法--简单易懂版_i++_03

 2.想缩短a、b两点间距离,只能引入第三个点k,甚至更多点,使得a->k->b、a->k1->k2…->k->i…->b能有更短距离

      假如现在只允许经过1号顶点,求任意两点之间的最短路程,应该如何求呢?只需判断e[i][1]+e[1][j]是否比e[i][j]要小即可。e[i][j]表示的是从i号顶点到j号顶点之间的路程。e[i][1]+e[1][j]表示的是从i号顶点先到1号顶点,再从1号顶点到j号顶点的路程之和。其中i是1~n循环,j也是1~n循环,代码实现如下。



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


在只允许经过1号顶点的情况下,任意两点之间的最短路程更新为:

            Floyd算法--简单易懂版_html_04

 接下来继续求在只允许经过1和2号两个顶点的情况下任意两点之间的最短路程



//经过1号顶点
for(i=1;i<=n;i++) {
for(j=1;j<=n;j++) {
if (e[i][j] > e[i][1]+e[1][j])
e[i][j]=e[i][1]+e[1][j];
}
}
//经过2号顶点
for(i=1;i<=n;i++) {
for(j=1;j<=n;j++) {
if (e[i][j] > e[i][2]+e[2][j])
e[i][j]=e[i][2]+e[2][j];
}
}


            Floyd算法--简单易懂版_i++_05

(个人理解:先更新经过1,在更新经过2,实质在更新2时,已经确定了a->1->2->b的最近距离,所致只需要逐一更新所有中间点,就遍历了所有a->k1->k2…->k->i…->b的可能场景,最终得到的必然是最优值)

 因此:整个算法过程虽然说起来很麻烦,但是代码实现却非常简单,核心代码只有五行:


 


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和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程


 注意:Floyd-Warshall算法不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路,永远找不到最短路。   

         Floyd算法--简单易懂版_html_06