2.图论经典算法之最短路~FLOYD

这大概是图论最基础的算法之一吧,本篇主要介绍佛洛依德(floyd)求图中任意两点之间的最短距离




弗洛伊德(Floyd)

采用邻接矩阵存图,n*n的矩阵存储点到点的最短距离

这里首先介绍一下动态规划(dp)的思想,给出三个点v1 v2 v3,你已经知道v1到v2的最短距离为1,v2到v3的嘴短距离为2,v1通过v2再到v3的最短距离显然为1+2,而在你存贮中的v1到v3却有可能比3长,有可能比3短,也可能就是3,如果比3长,显然需要更新这个数据,没错,Floyd就是不断的利用中间点来更新起点和终点之间的最短距离,最后达到求出任意两点的最短路长度的算法,他也是本篇介绍的算法中唯一一个不是求单源最短路径的算法(单源最短路径只能求出给定一点到其他点的最短路,而无法得知任意两点之间的最短路,看不懂不要紧,看到后面会明白的)

上图,图中是我们建完图所得到的初始n*n数组,这里要额外讲一个小技巧,在我们没有开始输入边的信息的时候,所有的点都是不相连的,所以,这个时候应该初始化矩阵内全为无限大,当然我们下意识的就想到遍历一遍都给他一个超大的值来表示不能到达,没错,介绍一个好用的函数,memset,使用之前要包括头文件


#include<string.h>

memset(mem,0x3f,sizeof(mem))

这个函数其实是对字节进行操作,第一个参数是地址,这里也就是mem数组的名字,0x3f其实就是63,众所周知一个字节有8比特,0x3f其实就是01111111,其实就是把这个字节变成011111111,这样得到的int或者long类型就会是一个很大的数,不赘述,不懂的自己搜索引擎,sizeof(mem)就是mem数组所占长度,这个参数的意思就是对给定位置(第一个参数)后面的第三参数的长度的字节进行初始化!另外需要提醒的是,此函数虽然方便,但是速度较慢,如果卡常,建议手写初始化。

主要算法,其实就是个三层循环,第一层k枚举的是中转点,第二层i枚举起点,第三层j枚举终点,只要以k为中转点可以更新i到j的距离,那就更新,时间复杂度n的三次方,比较暴力,一般不常用,但是还是要理解动态规划的思想!(引用我认为讲的最好的一段话:最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从i号顶点到j号顶点只经过前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和2都可以被中转


1和2和3都可以被中转

更新完毕

是不是很简单啊,如果还没明白自己画一个图模拟一遍就懂啦(图源网络)!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,417评论 0 2
  • Floyd 算法 简介 Floyd 算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径...
    廖少少阅读 8,669评论 0 1
  • [编程题]比较重量小明陪小红去看钻石,他们从一堆钻石中随机抽取两颗并比较她们的重量。这些钻石的重量各不相同。在他们...
    骇客与画家阅读 853评论 0 0
  • 求图的最短路径(详谈Floyd和Dijkstra) (注:在这一部分起点、源点意思相近;点的距离、边的长度、权值意...
    _黑色吊椅阅读 2,812评论 0 9
  • 今天我上午我的三号本丢了。我有三节语文课,第二节语文课丢了我三号本。我把作业本拿走了郝老师判作业,然后到第三节老师...
    小欣乐阅读 157评论 0 0