ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

6.1 最短路径:Floyd-Warshall算法

2021-11-19 11:03:36  阅读:130  来源: 互联网

标签:Warshall 路径 int 算法 Floyd 6.1 我们


Floyd-Warshall算法

只有五行核心的算法

简介

假设我们有四个点。每个点之间都有一定的距离,或者甚至没有路
现在我们想要知道如何获得两点之间的最短路径
使用之前说的深度优先或者宽度优先当然是可以的,不过有没有更好的办法?
于是我们使用了Floyd-Warshall,先进了一些的算法

算法核心

首先我们要知道,有的时候,通过n个点而从A->B,是有可能比直达得到更短的路径
基于这个思路,我们逐步推进
1.首先是直达,这个就不用说了
2.然后我们假设“如果允许在点1中转”,得到新的结果比较,更新数据
3.慢慢来,随后假设“如果允许在点1和点2中转”,再次更新数据
4.遍历所有可能,得到最终结果

实现

具体怎么实现呢,我们先做一波基础操作
首先首先,我们同样用一个二维数组e来存储路径情况(其实就是图的信息)
然后是比较,以顶点1为例,可以写成:

    for(i=1;i<=n,i++)
    {
        for(j=1;j<=n;j++)
        {
            if(i[e][j] > e[1][j]+e[1][j]){
                e[i][j] = e[i][1]+e[1][j]
                //如果途径1的路程e[1][j]+e[1][j]更小
                //那么把i到j的最短距离更新为e[i][j]+e[1][j]的大小   
                //这里实际就是比较了“当可以途径点1的时候
                //路径是否能够缩短”
            }
        }
    }

点2,点3,点4...都是同理,于是我们使用一个循环解决这件事情:

    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];

简单粗暴的五行,包含了Floyd-Warshall算法的思想

一句话概括,Floyd-Warshall算法就是:
从i号顶点到j号顶点,只经过前k号点时,其最短路径
通过不断推进,我们最终可以得到从i到j的最短路径

代码实例

    #include <stdio.h>
    int main()
    {
        int e[10][10],k,i,j,n,m,t1,t2,t3;
        int inf = 99999999 ; //预设的“正无穷”

        //读入n和m,n表示顶点个数,m表示边的条数  

        //各种花里胡哨的事情的初始化    
        
        //读入图
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(i==j)    e[i][j] = 0 ;
                else        e[i][j] = inf ;
        
        //读入边    
        for(i=1;i<=m;i++)
        {
            scanf("%d %d %d",&t1,&t2,&t3);
            e[t1][t2] = t3 ;
        }

        //Floyd-Warshall算法 
        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];
        
        //最终的输出    
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                printf("%10d",e[i][j]);
            }
            printf("\n");
        }

        return 0 ;
    }

其实把9999999定义成正无穷还是挺乱挺麻烦的,而且天知道会不会有bug
于是我们还可以增加一些判断条件来改善一下情况

    //Floyd-Warshall算法 
    for(k=1;k<=n;k++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(e[i][k]<inf && e[k][j]<inf && e[i][j] > e[i][k]+e[k][j])
                    e[i][j] = e[i][k]+e[k][j];

另外...

Floyd-Warshall算法可以处理带有负权边的图
但是没办法处理带有“负权回路”(也叫"负权环")的图

标签:Warshall,路径,int,算法,Floyd,6.1,我们
来源: https://www.cnblogs.com/RetenQ/p/15576123.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有