Floyd算法详解

合集下载

Floyd算法(各对顶点之间的最短距离)

Floyd算法(各对顶点之间的最短距离)

Floyd算法(各对顶点之间的最短距离)Floyd算法(各对顶点之间的最短距离)在上篇文章中议论到了如何求算单源最短路径,因此要想求各对顶点之间的距离,只需循环求算n次即可。

还有另外一种办法来求算各对顶点之间的最短距离,就是Floyd算法,因为其算法过程比Dijksa更简单理解,并且代码更简洁,因此当求算各对顶点之间的最短距离常采纳Floyd算法。

一.Floyd算法假设从i到j的最短路径上要经过若干个顶点,这些中间顶点中最大的顶点编号为k,最小的顶点为t,因此要求算dist[i][j]的最小值,那么只需要求算dist[i][s]+dist[s][j](t =s =k)的全部值,并取其中最小者即可。

因此可以设置一个中间顶点k(0 =k n)分离插入到每队顶点(i,j)之中,并更新dist[i][j]的值。

当n个顶点插入到每队顶点之中,求解便结束了。

其实Floyd算法实质上是一个动态规划算法。

代码实现: /*每对顶点之间最短路径Floyd 2011.8.27*/ iludeiostream include stack define M 100define N 100using namespace std;typef struct node{ int matrix[N][M]; //邻接矩阵 int n; //顶点数 int e; //边数 }MGraph; vo FloydPath(MGraph g,intdist[N][M],int path[N][M]){ int i,j,k; for(i=0;i g.n;i++)for(j=0;j g.n;j++) { if(g.matrix[i][j] 0){ dist[i][j]=g.matrix[i][j]; path[i][j]=i; } ee { if(i!=j) { dist[i][j]=INT_MAX; path[i][j]=-1; } else { dist[i][j]=0; path[i][j]=i; } } } for(k=0;k g.n;k++) //中间插入点(注重理解k为什么只能在最外层) for(i=0;i g.n;i++) for(j=0;jg.n;j++) { if((dist[i][k] 0 dist[i][k] INT_MAX) //防止加法溢出 (dist[k][j] 0 dist[k][j] INT_MAX) dist[i][k]+dist[k][j] dist[i][j]) { dist[i][j]=dist[i][k]+dist[k][j];path[i][j]=path[k][j]; //path[i][j]记录从i到j的最短路径上j 的前一个顶点 } } }void showPath(int path[N][M],int s,int t) //打印出最短路径 { stack int st; int v=t; while(t!=s) { st.push(t);第1页共2页。

floyd算法步骤详解

floyd算法步骤详解

floyd算法步骤详解Floyd算法步骤详解Floyd算法,又称为弗洛伊德算法,是一种解决任意两点间最短路径的算法。

该算法的核心思想是动态规划,通过遍历每一个中间节点来更新每条路径上的最短距离。

下面,我们来详细了解一下Floyd算法的步骤。

步骤1:构造邻接矩阵我们需要构造出一个邻接矩阵,用来表示地图上的各个节点之间的连接情况。

邻接矩阵一般用二维数组来表示,其中数组的下标表示节点编号,数组的值表示两个节点之间的距离或权值。

如果两个节点之间没有连接,则可以用一个很大的数表示它们之间的距离。

步骤2:初始化距离矩阵接下来,我们需要初始化一个距离矩阵,用来存储任意两点之间的最短距离。

距离矩阵同样也是一个二维数组,其中数组的下标表示起点和终点的节点编号,数组的值表示两个节点之间的最短距离。

初始化的时候,如果两个节点之间有连接,则距离矩阵中的对应位置存储的值为它们之间的距离,否则设置为一个很大的数。

步骤3:遍历中间节点接下来,我们需要遍历每一个中间节点,更新距离矩阵中的值。

具体的遍历方式是,从起点到终点遍历所有的中间节点,如果中间节点可以使起点和终点之间的距离更短,则更新距离矩阵中的值。

步骤4:更新距离矩阵在遍历中间节点的过程中,我们需要不断地更新距离矩阵中的值。

具体的更新方式是,如果起点到中间节点的距离加上中间节点到终点的距离小于起点到终点的距离,则更新距离矩阵中对应的值。

步骤5:输出最短路径在完成所有的遍历之后,距离矩阵中存储的就是任意两点之间的最短距离。

我们可以根据这个矩阵来输出任意两点之间的最短路径。

具体的输出方式是,从起点开始,依次找到距离它最近的节点,直到到达终点为止。

总结Floyd算法是一种经典的解决任意两点间最短路径的算法,虽然它的时间复杂度比较高,但是它的思想和实现方式都非常简单,容易理解。

如果你想深入学习算法和数据结构,那么Floyd算法是一个非常好的入门选择。

Floyd算法思想及操作详解

Floyd算法思想及操作详解

二、Warshall和Floyd算法
2. Floyd算法 • Floyd算法用于计算距离矩阵,即每个顶点到其他 所有顶点之间的距离(最短路径的长度)
二、Warshall和Floyd算法
2. Floyd算法 • 算法思想 – 算法考虑每对顶点最短路径上的中间顶点 – dij (k)等于从第i个顶点到第j个顶点之间所有路径 中一条最短路径的长度,并且路径的每一个中 间顶点(如果有的话)的编号不大于k – 有递推关系式
DW for k 1 to n do for i 1 to n do for j 1 to n do D[i, j] min{D[i, j], D[i, k]+D[k, j]} return D
算法分析: 时间效率分析:Θ(n³ )
二、Warshall和Floyd算法
1. Floyd算法 • 例题 – p223,习题8.2,第7题:对下面具有权重矩阵 的有向图,求解完全最短路径 0 2 1 8 6 0 3 2 0 4 2 0 3 3 0 • 思考 – p223,习题8.2,第10题
二、Warshall和Floyd算法
Floyd算法
a 2 7 b 3


c
1
6
d
二、Warshall和Floyd算法
二、Warshall和Floyd算法
2. Floyd算法 • 算法
Floyd(W[1..n,1..n]) // 实现计算完全最短路径的Floyd算法 // 输入:图的权重矩阵W // 输出:包含最短路径长度的距离矩阵
( ( ( ( dijk ) min{dijk 1) , dikk 1) d kjk 1) }, (0) dij wij

Floyd算法

Floyd算法

Floyd算法Floyd算法是一种经典的图论算法,用于求解带权有向图中任意两个顶点之间的最短路径问题。

该算法由美国数学家罗伯特·弗洛伊德(Robert Floyd)于1962年提出,因此得名为Floyd算法。

Floyd算法是一种动态规划算法,它采用了“分治”的思想,将问题分解为更小的子问题,然后逐步解决子问题,最终得到解决整个问题的结果。

本文将从算法的背景、基本思想、实现方法及优缺点等方面对Floyd 算法进行详细阐述和分析。

一、算法的背景在讲Floyd算法之前,我们先来了解一下最短路径问题。

顾名思义,最短路径问题就是在给定图中找到两个给定节点之间的一条最短路径,也就是路径上各边权值之和最小的路径。

这个问题在现实生活中有很多应用,比如网络路由、地图路径规划、航线安排等等。

在数学和计算机科学领域中,我们可以通过图论的方法来描述和解决这个问题。

一般来说,给定一张带权有向图G=(V, E),其中V表示节点的集合,E表示边的集合。

每条边E(i,j)的权重为w(i,j),表示从节点i到节点j的距离或成本。

那么最短路径问题就是在图中找到从节点s到节点t的一条最短路径P,并且P上的边权之和最小。

最初求解的思路是按照类似深度优先搜索的方式,逐个遍历所有路径,然后依次比较它们的距离,找到最短路径。

但这种方式显然是不可行的,因为它的时间复杂度非常高。

所以,我们需要设计一种更高效的算法,以求得最短路径问题的最优解。

二、算法的基本思想Floyd算法就是一种高效地解决最短路径问题的方法。

它采用了“动态规划”的思想,通过逐步求解子问题,最终得到完整的最短路径。

而解决子问题的方式则是采用了“分治”的思想,将问题分解为更小的子问题,然后逐步解决。

具体地说,Floyd算法采用了“中转节点”的概念,我们可以将问题转化为这样一个子问题:对于每个节点i和节点j,假设我们已经知道了它们之间的最短路径长度为d[i][j],那么考虑一下节点k作为中转节点,它可以为i和j之间的路径P提供一个“中转服务”,将P拆分为两条路径:i-->k和k-->j。

简介Floyd算法

简介Floyd算法

简介Floyd 算法⽬录1. 定义Floyd 算法是⼀种⽤于寻找给定的加权图中顶点间最短路径,是经典的多源最短路径算法,可以有效地处理有向图或负权的最短路径问题,同时也被⽤于计算有向图的传递闭包。

Floyd 算法的时间复杂度为 O (N 3),空间复杂度为 O (N 2)。

2. 优缺点优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。

缺点:时间复杂度⽐较⾼,不是和计算⼤量数据。

3. 基本思想Floyd 算法属于动态规划算法,即寻找节点 i 到节点 j 的最短路径。

Step 1: 初始距离定义 n 节点⽹络的邻接矩阵 A n ×n ,矩阵中的元素为 a i ,j 为节点 i 到节点 j 的⼀步的直线距离。

令 A (0)=A ,其初始元素为 a (0)i ,j 则该距离有如下三种情况:a (0)i ,j =c i ,j , i ,j 相连0, i =j∞, i ,j 不相连其中,节点 i , j 之间有直线连接时,则 a (0)i ,j 为其距离值 c i ,j ;节点 i 到⾃⾝的距离为 0;节点 i , j 之间没有直线连接时,则 a (0)i ,j 则为 ∞,如下图:则该初始邻接矩阵 A 为:即节点0与节点0⾃⾝距离值为0,即 A [0][0]=0;节点0与节点1之间有直线连接,距离值为5,即 A [0][1]=5;节点0与节点2之间没有直线连接,则距离值为 ∞,即 A [0][2]=∞;节点0与节点3之间有直线连接,距离值为7,即 A [0][3]=7 ……其他节点间的初始距离可依次写出,即为该邻接矩阵 A 。

Step 2: 借中转节点迭代找最短路径节点 i , j 间⼀步达不到时,则需要在两节点之间通过其他节点(如节点 k )作连接:在 A 矩阵上做 n 次迭代,k =1,⋯,n ,第 k 次迭代a k i ,j =min (a k −1i ,j ,a k −1i ,k +a k −1k ,j )即在节点 i 和节点 j 之间找到⼀条最短距离的路径,如下图:图中的节点 i 到节点 j 之间的直线距离 (i →j ) 为 6,但经过节点 k 作中转后,节点 i 到节点 j 之间的直线距离 (i →k →j ) 为 2+3=5,因此 a k i ,j =min (6,5)=5。

Floyd算法

Floyd算法

Floyd算法求助编辑百科名片弗洛伊德算法Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。

改算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。

目录核心思路算法过程时间复杂度优缺点分析改进和优化算法实现pascal语言java算法展开核心思路算法过程时间复杂度优缺点分析改进和优化算法实现pascal语言java算法展开编辑本段核心思路通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。

从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。

矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

采用的是(松弛技术),对在i和j之间的所有其他点进行一次松弛。

所以时间复杂度为O(n^3);其状态转移方程如下:map[i,j]:=min{map[i,k]+map[k,j],map[i,j]}map[i,j]表示i到j的最短距离K是穷举i,j的断点map[n,n]初值应该为0,或者按照题目意思来做。

当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路编辑本段算法过程1,从任意一条单边路径开始。

所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。

2,对于每一对顶点u 和v,看看是否存在一个顶点w 使得从u 到w 再到v 比己知的路径更短。

如果是更新它。

编辑本段时间复杂度O(n^3)编辑本段优缺点分析Floyd算法适用于APSP(All Pairs Shortest Paths),是一种动态规划算法,稠密图效果最佳,边权可正可负。

java算法 floyd算法

java算法 floyd算法

java算法 floyd算法Floyd算法是一种用于解决图中所有节点之间最短路径问题的算法。

该算法以其简洁高效的特点而被广泛应用于网络路由算法、城市交通规划等领域。

本文将详细介绍Floyd算法的原理和实现过程。

一、算法原理Floyd算法采用动态规划的思想,通过不断更新节点之间的最短路径来求解问题。

它的核心思想是,假设图中的节点集合为V,任意两个节点i和j之间的最短路径为d(i,j),则对于任意节点k,如果节点k在节点i和节点j之间作为中转节点,则节点i和节点j之间的最短路径可以通过节点k来实现,即d(i,j) = min{d(i,k) + d(k,j)}。

基于这个思想,Floyd算法通过不断更新所有节点之间的最短路径,最终得到所有节点之间的最短路径。

二、算法实现下面我们详细介绍Floyd算法的实现过程。

1. 初始化我们需要定义一个二维数组dist,用于存储任意两个节点之间的最短路径长度。

如果节点i和节点j之间有边相连,则dist[i][j]的值为边的权重;如果节点i和节点j之间没有边相连,则dist[i][j]的值为无穷大。

同时,我们还需要定义一个二维数组path,用于存储节点i和节点j之间的最短路径经过的节点。

2. 更新最短路径接下来,我们使用三层循环来更新所有节点之间的最短路径。

外层循环遍历所有节点k,中层循环遍历所有节点i,内层循环遍历所有节点j。

在每次循环中,我们判断节点i和节点j之间的最短路径是否可以通过节点k来实现,如果可以,则更新最短路径和路径经过的节点。

3. 输出最短路径我们可以通过遍历dist数组来输出任意两个节点之间的最短路径长度。

同时,我们还可以通过遍历path数组来输出任意两个节点之间的最短路径经过的节点。

三、算法分析Floyd算法的时间复杂度为O(n^3),其中n为图中节点的个数。

该算法的空间复杂度为O(n^2),因为需要使用一个二维数组来存储任意两个节点之间的最短路径长度。

v 弗洛伊德算法

v 弗洛伊德算法

v 弗洛伊德算法弗洛伊德算法(Floyd’s algorithm),又称为插点法,是一种通过动态规划求解最短路径问题的算法。

该算法在图论中有着广泛的应用,能够快速求解出两点之间的最短路径。

本文将为大家介绍弗洛伊德算法的原理以及实际应用。

1. 算法原理弗洛伊德算法的核心思想是利用中间点来更新起点到终点的距离。

假设图中任意两点之间的距离都为$d[i][j]$,则我们假设存在一个中间点$k$,可以将起点$i$和终点$j$之间的最短路径分成两部分,即起点到中间点的路径$d[i][k]$和中间点到终点的路径$d[k][j]$。

所以我们可以得到如下的状态转移方程:$$d[i][j]=\min(d[i][j],d[i][k]+d[k][j])$$通过不断地更新所有点之间的最短路径,我们最终可以得到所有节点之间的最短路径。

2. 算法实现弗洛伊德算法的实现中,最重要的一步就是更新状态转移方程。

具体来说,我们需要使用三层循环嵌套遍历所有点,将当前节点到所有其他节点的最短距离更新一遍即可。

下面就是使用 Python 语言实现弗洛伊德算法的代码片段:```pythonn = len(graph)for k in range(n):for i in range(n):for j in range(n):graph[i][j] = min(graph[i][j], graph[i][k] +graph[k][j])```在这段代码中,$graph$是一个$n \times n$的矩阵,表示所有节点之间的距离。

其中$n$是节点的数量。

3. 算法应用弗洛伊德算法的主要应用是求解带权图中各个节点之间的最短路径。

在实际生活中,我们可以将节点看作是城市,将距离看作是两个城市之间的道路距离。

这样,就可以使用弗洛伊德算法来计算任意两座城市之间的最短路程,帮助人们规划出更加便捷的旅行路线。

另外,在计算机网络中,弗洛伊德算法也被广泛应用于路由协议的设计中。

Floyd算法简介

Floyd算法简介

Floyd算法简介⼀.Floyd算法的介绍1.算法的特点:弗洛伊德算法是解决任意两点间的最短路径的⼀种算法,可以正确处理⽆向图或有向图或负权(仅适合权值⾮负的图)的最短路径问题,同时也被⽤于计算有向图的传递闭包。

2.算法的思路: 通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引⼊两个矩阵,矩阵S中的元素a[i][j]表⽰顶点i(第i个顶点)到顶点j(第j个顶点)的距离。

矩阵P(记录最短路的路径需要,若题⽬不需要求路径则不需要P数组)中的元素b[i][j],表⽰顶点i到顶点j经过了顶点b[i][j]。

假设图G中顶点个数为N,则需要对矩阵D和矩阵P进⾏N次更新。

初始时,矩阵D中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞,矩阵P的值为顶点b[i][j]的j的值。

接下来开始,对矩阵D进⾏N次更新。

第1次更新时,如果”a[i][j]的距离” > “a[i][0]+a[0] [j]”(a[i][0]+a[0][j]表⽰”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”,更新b[i][j]=b[i][0]。

同理,第k次更新时,如果”a[i][j]的距离” > “a[i][k-1]+a[k-1][j]”,则更新a[i][j]为”a[i][k-1]+a[k-1][j]”,b[i][j]=b[i][k-1]。

实质上是背包DP问题,最外层循环是k,表⽰利⽤前k个作为中间计算a[i][j]的最⼩值,本来需要三位数组a[k][i][j],因为第k次循环只会⽤到a[k-1][i][j],所以利⽤滚动数组,使⽤⼆维数组即可。

更新N次之后,操作完成!时间复杂度为O(N^3),空间复杂度为O(N^2)。

核⼼代码:1for(k=0;k<n;k++)2for(i=0;i<n;i++)3for(j=0;j<n;j++)4if(a[i][j]>a[i][k]+a[k][j])5 a[i][j]=a[i][k]+a[k][j],b[i][j]=b[i][k]; 只有5⾏!现在你会发现这个看起来很⾼⼤上的算法很简单了,算是最短路的4个算法⾥最暴⼒的了! 3.实例: 题意:有n种动物,m种直接转换的咒语,且转换具有传递性,求从哪⼀种动物到另⼀种的动物的最长咒语的最⼩值,若不能转换到所有动物,则输出0. 思路:Floyd算法的裸应⽤,将动物抽象为点,咒语长度抽象为边的权值,代码如下:#include<bits/stdc++.h>using namespace std;const int inf=0x3f3f3f3f;int n,m,a,b,c;int mp[105][105];int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)if(i!=j) mp[i][j]=inf;while(m--){scanf("%d%d%d",&a,&b,&c);mp[a][b]=c;mp[b][a]=c;}for(int k=1;k<=n;++k)for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)if(mp[i][j]>mp[i][k]+mp[k][j])mp[i][j]=mp[i][k]+mp[k][j];int maxi,minv=0,res=inf;for(int i=1;i<=n;++i){maxi=0;for(int j=1;j<=n;++j)if(mp[i][j]>maxi)maxi=mp[i][j];if(maxi<res)res=maxi,minv=i;}if(minv)printf("%d %d\n",minv,res);elseprintf("0\n");return0;}。

弗洛伊德(Floyd)算法

弗洛伊德(Floyd)算法

弗洛伊德(Floyd)算法最短路径问题:从某个顶点出发到达另外⼀个顶点的所经过的边的权重和最⼩的⼀条路径弗洛伊德算法解决最短路径问题1.基本思想(1)计算图中各个顶点之间的最短路径,每⼀个顶点都是出发访问点,所以需要将每⼀个顶点看做被访问顶点,求出从每⼀个顶点到其他顶点的最短路径(2)所有顶点都作为中间节点遍历⼀次,每次遍历将各个顶点经过中间节点到另⼀个节点的距离,与不经过该节点的距离相⽐较,若经过中间节点的距离更⼩,就更新距离表与前驱关系(3)时间复杂度O(n3),所有顶点作为出发点、中间节点、终点,每个顶点都要遍历3次2.步骤(1)设置顶点 a 到顶点 b 的最短路径已知为 L ab,顶点 b 到 c 的最短路径已知为 L bc,顶点 a 到 c 的路径为 L ac,则 a 到 c 的最短路径为:min ( ( L ab + L bc ), L ac ),b 的取值为图中所有顶点,则可获得 a 到 b 的最短路径(2)⾄于 a 到 b 的最短路径 L ab或者 b 到 c 的最短路径 L bc,是以同样的⽅式获得(3)三个点为同⼀顶点时:中间顶点为⾃⾝;三个点是不同顶点时:中间顶点是终点的前驱节点;两个顶点直接连通时:中间节点为出发点代码实现import java.util.Arrays;public class Floyd {//弗洛伊德算法解决最短路径问题public static final int BLOCK = 65535;//表⽰顶点之间不直接连通public static void main(String[] args) {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};//顶点到⾃⾝距离为0int[][] matrix = {{0, 5, 7, BLOCK, BLOCK, BLOCK, 2},{5, 0, BLOCK, 9, BLOCK, BLOCK, 3},{7, BLOCK, 0, BLOCK, 8, BLOCK, BLOCK},{BLOCK, 9, BLOCK, 0, BLOCK, 4, BLOCK},{BLOCK, BLOCK, 8, BLOCK, 0, 5, 4},{BLOCK, BLOCK, BLOCK, 4, 5, 0, 6},{2, 3, BLOCK, BLOCK, 4, 6, 0}};Graph graph = new Graph(matrix, vertex);graph.floyd();graph.result();}}//带权⽆向图class Graph {public char[] vertex;//存放顶点public int[][] matrix;//保存各个顶点到其它顶点的距离,初始为直接连接的距离,算法计算后为最短距离public int[][] relay;//保存中间结点//构造器public Graph(int[][] matrix, char[] vertex) {this.vertex = vertex;this.matrix = matrix;this.relay = new int[vertex.length][vertex.length];//三个点为同⼀顶点时:中间顶点为⾃⾝;三个点是不同顶点时:中间顶点是终点的前驱节点;两个顶点直接连通时:中间节点为出发点for (int i = 0; i < vertex.length; i++) {Arrays.fill(relay[i], i);//初始中间顶点为⾃⾝}}//显⽰算法结果public void result() {for (int k = 0; k < vertex.length; k++) {for (int i = 0; i < vertex.length; i++) {System.out.println(vertex[k] + " 到 " + vertex[i] +" 最短路径 " + matrix[k][i] +" 中间结点 " + vertex[relay[k][i]]);}System.out.println();}}//弗洛伊德算法public void floyd() {int temp;//保存i到j的距离for (int i = 0; i < matrix.length; i++) {//出发点ifor (int j = 0; j < matrix.length; j++) {//中间顶点jfor (int k = 0; k < matrix.length; k++) {//终点ktemp = matrix[i][j] + matrix[j][k];//求从i出发,经过k,到达j的距离 if (temp < matrix[i][k]) {matrix[i][k] = temp;//更新距离relay[i][k] = relay[j][k];//更新中间顶点}}}}}}。

Floyd算法详解

Floyd算法详解

Floyd算法详解Floyd-WarshallFloyd算法,是⼀种著名的多源最短路算法。

核⼼思想:⽤邻接矩阵存储图,核⼼代码为三重循环,第⼀层枚举中间点k,⼆三层分别枚举起始点i与⽬标点j。

然后判断经过中间点k后,i与j间的路程是否会减⼩。

如果是,就更新i,j之间的最短路。

for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(e[i][j]>e[i][k]+e[k][j])e[i][j]=e[i][k]+e[k][j];需要注意的是,为了保证更新成功,需要将e数组初始化为⽆穷⼤。

同时为了防⽌程序做⽆意义的到⾃⼰的最短路,将每个节点到本⾝的距离初始化为0。

算法复杂度:该算法的空间复杂度为n^2(不算优秀,但勉强接受),时间复杂度O(n^3)(呵呵)。

完整代码:#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int inf=99999999;int n,m,x,y,z,s;int dis[1001][1001];int main(){scanf("%d%d%d",&n,&m,&s);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j) dis[i][j]=inf;else dis[i][j]=0;for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);dis[x][y]=dis[y][x]=z;}for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(dis[i][k]+dis[k][j]<dis[i][j])dis[i][j]=dis[i][k]+dis[k][j];for(int i=1;i<=n;i++)printf("%d ",dis[s][i]);return0;}算法优化:for(int k = 1; k <= n; k++)for(int i = 1; i <= n; i++)for(int j = 1; j <= i; j++)dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j]),dis[j][i] = dis[i][j];这⾥利⽤了矩阵的对称性,只更新⼀半矩阵即可。

弗洛伊德算法实用技巧

弗洛伊德算法实用技巧

弗洛伊德算法实用技巧弗洛伊德算法(Floyd's Algorithm),又称为最短路径算法,是一种用于求解图中各顶点之间最短路径的算法。

它以其简洁高效的特点而被广泛应用于图论和网络优化领域。

本文将介绍弗洛伊德算法的原理及其在实际问题中的应用技巧。

一、弗洛伊德算法原理弗洛伊德算法的核心思想是采用动态规划的方法,通过逐步更新每一对顶点之间的最短路径长度,直到得到所有顶点之间的最短路径。

具体步骤如下:1. 初始化最短路径矩阵:以邻接矩阵的形式表示图的边权重,初始化一个大小为n×n的矩阵D,其中n为顶点个数。

若顶点i和顶点j之间存在边,则D[i][j]的值为边的权重;若不存在边,则D[i][j]的值为一个较大的数(如∞)。

2. 进行顶点中转:对于每一对顶点i和j,以顶点k作为中转点,更新D[i][j]的值,使其等于D[i][k] + D[k][j]和D[i][j]中的较小值。

即,若通过顶点k的路径更短,则更新D[i][j]的值。

3. 重复进行中转:依次选择每一个顶点作为中转点,进行步骤2的操作。

当所有顶点均作为中转点完成一次中转后,得到的矩阵D即为最终的最短路径矩阵。

二、弗洛伊德算法应用技巧1. 求解最短路径:弗洛伊德算法可以用于求解有向图或无向图中任意两点之间的最短路径。

通过获取最短路径矩阵D,即可得到任意一对顶点之间的最短路径长度。

2. 检测负权回路:在求解最短路径的过程中,若在最终的最短路径矩阵D中存在D[i][i]为负数的情况,则说明图中存在负权回路,即图中存在一个环路,其权重之和为负数。

该特性可用于识别图中是否存在负权回路。

3. 网络拓扑排序:弗洛伊德算法可以用于进行网络拓扑排序。

在求解最短路径的过程中,通过检测矩阵中的负权回路,可以得到顶点的拓扑排序结果。

拓扑排序用于评估任务执行的顺序,从而实现任务的优化调度。

4. 交通网络优化:弗洛伊德算法可以用于优化交通网络的设计。

通过将道路或路径作为图中的边,顶点表示城市或路口,权重表示通行距离或时间,利用最短路径矩阵D,可以评估不同路径的通行效率,从而优化道路规划和交通流量调度。

Floyed(floyd)算法详解

Floyed(floyd)算法详解

Floyed(floyd)算法详解是真懂还是假懂?Floyed算法:是最短路径算法可以说是最慢的⼀个。

原理:O(n^3)的for循环,对每⼀个中间节点k做松弛(寻找更短路径);但它适合算多源最短路径,即任意两点间的距离。

但spfa,迪杰斯特拉就只能算⼀个点到其他任⼀点的最短路径。

关键在于,我们真的真正理解floyed吗?就是因为它太短了,以⾄于我们有些⼈(神仙除外)看代码后看到这样⼀个语句:d[i][j]=min(d[i][j],d[i][k]+d[k][j])也就是说,对于每⼀个中转点k来说,进⾏O(n^2)的松弛,⼀定能找到最短路径。

虽不是最优,但是松弛次数来凑!这⼤概就是我们(之前的我)的⽆须证明的,想当然的理解,并背下来了它,以便以后想TLE时⽤。

(O(n^3));so?Floyed本质是dp;递推公式:(图⽚源⾃⽹络⼤佬)众所周知,dp(动态规划)要满⾜⽆后效性。

也就是说。

还是先举个例⼦:我们设k取某⼀个k1时满⾜k1为最终点i到j最短路经过的点,但是在外层循环到k1时d[i][k1]和d[k1][j]并没有取到最⼩值,因为k1只能取⼀次,那么往后再循环是不是就取不到k1了呢??答案当然不是的(不然这个算法为什么正确?)还是那句话,dp⽆后效性,也就是说,k不单单是枚举,还是⼀个状态变量,找i和j之间通过编号不超过k(k从1到n)的节点的最短路径(⼀定要注意,这⾥是当前最短路径,k之前的已经变成最短路了,对于每⼀个k,我们都进⾏了n^2的充分枚举(ij),已保证当前已经满⾜对从1到k的节点最优,那么当k枚举完所有点,那么⼀定是最优的了换句话说,在d[i][j]=min(d[i][j],d[i][k]+d[k][j])公式中,因为k之前已经作为i或者j被枚举过了;,d[i][k]和d[k][j]已经被1到k枚举过了那么他们⼀定是1到k节点中最优的路径,等枚举到n时,所有的都枚举完了,那么它们就是基本代码: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] )如果直接到达⽐通过k这个中转接点到达的距离短e[i][j]=e[i][k]+e[k][j];那么就更新松弛算法复杂度O(n^3),这也是为什么平常很少使⽤的原因。

Floyd算法

Floyd算法

Floyd算法Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。

核心思路:通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。

从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。

矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path 来记录两点间的最短路径。

算法过程:把图用邻接距阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。

定义一个距阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。

把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。

在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。

比如,要寻找从V5到V1的路径。

根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。

优缺点分析:Floyd算法适用于APSP(All Pairs Shortest Paths),稠密图效果最佳,边权可正可负。

此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。

优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单;缺点:时间复杂度比较高,不适合计算大量数据。

Floyd算法的基本思想:(1)利用二维数组A[1..n-1][1..n-1], A[i][j]记录当前vi到vj的最短路径长度,数组A的初值等于图的代权临街矩阵;(2)集合S记录当前允许的中间顶点,初值S=Φ;(3)依次向S中加入v0 ,v1… vn-1,每加入一个顶点,对A[i][j]进行一次修正:设S={v0 ,v1… vk-1},加入vk,则A(k)[i][j] = min{ A(k-1)[i][j],A(k-1)[i][k]+A(k-1)[k][j]}。

数学建模floyd算法最短路算法详解

数学建模floyd算法最短路算法详解
二算法原理1求距离矩阵的方法2求路径矩阵的方法3查找最短路路径的方法一算法的基本思想三算法步骤算法的基本思想直接在图的带权邻接矩阵中用插入顶点的方法依次构造出?个矩阵d1d2
最短路算法
任意一对顶点之间的最短路算法:Floyd算法
(一)算法的基本思想
(二)算法原理 1、求距离矩阵的方法 2、求路径矩阵的方法 3、查找最短路路径的方法
选址问题--中心问题
例 2 某城市要建立一个消防站,为该市所属的七个区服务, 如图所示.问应设在那个区,才能使它至最远区的路径最短.
(1)用 Floyd 算法求出距离矩阵 D= (dij ) .
(2) 计算在各点vi 设立服务设施的
最大服务距离S (vi ) .
S (vi
)

max{d
1 j
算法原理—— 查找最短路路径的方法
若 rij( ) p1,则点 p1 是点 i 到点 j 的最短路的中间点.
然后用同样的方法再分头查找.若:
(1)向点 i 追朔得:rip(1 )

p2
r,
( ) ip 2

p3 ,…,rip(k )

pk
(2) 向点
j
追朔得:
r ( ) p1 j

q1
1 4 4 4 4 4 2 3 3 3
D


5
2
0
2
4 ,
R


4
2
3
4
5

3 4 2 0 6
1 3 3 4 3

9
6
4
6
0


4
3
3
3
5

floyd判圈法

floyd判圈法

Floyd判圈法一、引言在计算机科学中,Floyd判圈法(Floyd’s cycle-finding algorithm)是一种用于判断有向图中是否存在环的算法。

该算法由罗伯特·弗洛伊德(Robert W. Floyd)于1967年提出,因此得名。

Floyd判圈法通过使用两个指针在图中移动来判断是否存在环,并且可以找到环的起点。

二、算法原理Floyd判圈法的原理非常简单,主要分为以下几个步骤:1.定义两个指针,一个快指针(每次移动两步)、一个慢指针(每次移动一步)。

2.快指针从起点开始移动,慢指针从起点的下一个节点开始移动。

3.如果存在环,快指针最终会追上慢指针,两个指针会相遇。

4.如果不存在环,快指针会提前到达终点。

三、算法步骤下面详细介绍Floyd判圈法的具体步骤:1. 初始化指针设定两个指针,一个指向图中的起点,另一个指向起点的下一个节点。

slow_pointer = head.nextfast_pointer = head.next.next2. 移动指针通过不断移动指针来判断是否存在环。

while slow_pointer != fast_pointer:slow_pointer = slow_pointer.nextfast_pointer = fast_pointer.next.next3. 判断是否存在环当两个指针相遇时,即存在环,否则不存在环。

if slow_pointer == fast_pointer:return Trueelse:return False4. 寻找环的起点如果存在环,需要找到环的起点。

此时,将慢指针重新指向起点,快指针保持在相遇点,然后两个指针同时每次移动一步,直到相遇。

slow_pointer = headwhile slow_pointer != fast_pointer:slow_pointer = slow_pointer.nextfast_pointer = fast_pointer.nextreturn slow_pointer四、算法分析Floyd判圈法的时间复杂度为O(n),其中n表示链表的节点数。

floyd算法精讲

floyd算法精讲
D (2)[0][3] Min {D (1)[0][3], D (1) [0][2] D (1) [2][3]} Min {7, 3 2} 5 D (2) [1][3] Min {D (1) [1][3], D (1) [1][2] D (1)[2][3]} Min {9,2 2} 4
(step 0) D l ; //将有向网的邻接矩阵输入到D中 (step 1) for k = 1 to n 算法复杂度为 O(n^3) (step 3) for i = 1 to n (step 4) for j = 1 to n (step 5) D[i, j] = min{D[i, j], D[i, k] + D[k, j]} (step 6) end for (step 7) end for (step 8) end for
D (0) [i ][j ] Min {D ( 1)[i ][j ], D ( 1)[i ][0] D ( 1)[0][ j ]}
D (0) [1][3] Min {, D ( 1)[1][0] D ( 1)[0][3]} Min {, 2 7} Min {, 9} 9
D (1)[0][2] Min {D (0)[0][2], D (0)[0][1] D (0)[1][2]} Min {,1 2} 3 D (1)[3][2] Min {D (0)[3][2], D (0)[3][1] D (0)[1][2]} Min {,2 2} 4
(k ) 用公式表示就是,对于K=1,2,3…n,第k个矩阵 D( k ) dij
(k ) ( k 1) ( k 1) ( k 1) dij min{ dij , dik dkj }

Floyd算法

Floyd算法

Floyd 算法4.1 Floyd 算法简介Floyd 算法又称为弗洛伊德算法,是一种用于寻找给定的加权图中顶点间最短路径的算法[8]。

算法思想旨在通过对 Floyd 算法进行改进,从而更加简便有效地计算不含负回路网络中任意两节点之间的最短路。

初始权矩阵可由网络图直接得到,由计算时,中的元素是经过多次经转后得到的最短路长,即经过该次迭代计算出的最短路径可以经过多个中间节点。

在此基础上计算(2)(3)(),,...,k D D D , 当算出第k +1 个矩阵时, 如果 ,那么()D k 中的元素就是对应的节点对之间的最短路长值。

在计算权矩阵时,有时插入的中间节点与源点、汇点均不直接相连,因此计算出来的最短路长值不会改变,故这些点可以不参与计算。

另外,在计算最短路长前,先将待插入节点进行路长比较,若()()k k lj ij d d ≥或()()k k il ij d d ≥,则表明插入该节点后,不会使原来的路长变短,无需再计算 (1)k ij d + (因为 (1)()k k ij ijd d +=), 接着对下一个节点进行搜索。

文中采用下标直接标注的方法来标注最短路径, 当插入某个节点l v 后, 如果计算出来的最短路长值不会比原来的短, 那么就将该节点的下标l 直接标注在权矩阵中对应的元素的右下角, 表明最短路径经过该节点。

在不含负回路的网络中[9], 有节点12,,...,n v v v ,用ij w 表示节点 v i 和节点v j 之间的连线长,用ij d 表示从节点v i 出发到节点v j 时的路长。

Floyd 算法通常情况下也被人们称之为插点法,Floyd 算法是一种利用加权图进而进一步找到多源点之间最短路径问题的一种方法。

由于发明这种算法的最重要的人就是著名科学家罗伯特·弗洛伊德,因此这种算法就是用弗洛伊德的名字来命名的。

他在1978年的时候,依然在斯坦福大学计算机科学系担任教授的时候发明的这么一种最短路径算法。

floyd用法

floyd用法

floyd用法摘要:1.Floyd 算法简介2.Floyd 算法的基本思想3.Floyd 算法的适用场景4.Floyd 算法的计算步骤5.Floyd 算法的示例正文:1.Floyd 算法简介Floyd 算法是一种用于寻找加权图中所有顶点之间最短路径的算法,也被称为Floyd-Warshall 算法。

该算法由Robert C.Floyd 于1968 年提出,是图论领域中一种非常重要的算法。

2.Floyd 算法的基本思想Floyd 算法的基本思想是动态规划。

算法通过计算每个顶点之间的路径长度,然后利用这些信息来更新其他顶点之间的路径长度,最终得到所有顶点之间的最短路径。

3.Floyd 算法的适用场景Floyd 算法适用于存在负权边的图,并且可以处理边权值为负数的情况。

同时,Floyd 算法可以处理所有顶点之间的最短路径问题,无论是单源最短路径还是多源最短路径。

4.Floyd 算法的计算步骤Floyd 算法的计算步骤如下:(1) 初始化邻接矩阵dist,dist[i][j] 表示顶点i 到顶点j 的边的权值。

如果两个顶点之间没有边,可以将dist[i][j] 设为一个较大的值,如正无穷。

(2) 对于所有顶点k,计算dist[i][j] += dist[i][k] * dist[k][j],其中i、j、k 为顶点标号。

这一步的目的是通过累积每个顶点之间的路径长度来更新其他顶点之间的路径长度。

(3) 遍历所有顶点对(i, j),如果dist[i][j] 的值小于0,则说明在顶点i 到顶点j 的路径中存在一个环。

此时,可以将dist[i][j] 设为一个较大的值,如正无穷,以表示不存在从顶点i 到顶点j 的路径。

5.Floyd 算法的示例假设有一个图,顶点有A、B、C、D、E 五个,边的权值分别为1、2、3、1、4。

现在需要求解所有顶点之间的最短路径。

floyd法 -回复

floyd法 -回复

floyd法-回复floyd法(Floyd-Warshall algorithm)是一种用于解决带权有向图中所有顶点间最短路径问题的算法。

在现实生活中,我们经常面对着需要找到最短路径问题,比如在导航系统中确定最快的驾驶路线,或者在电信网络中寻找两个路由器之间的最短路径。

本文将详细介绍floyd法的原理和实施步骤。

floyd法的原理基于动态规划的思想。

它通过不断更新包含指定顶点集的子图中的最短路径,最终得到整个图中任意两个顶点之间的最短路径。

以下是floyd法的具体步骤:1. 初始化:- 创建一个二维数组`dist`,用于存储任意两个顶点之间的最短路径长度。

初始时,将`dist[i][j]`初始化为顶点i和j之间的直接距离,如果不存在直接距离,则设为无穷大。

- 创建一个二维数组`path`,用于存储任意两个顶点之间的最短路径中经过的中间顶点。

初始时,将`path[i][j]`初始化为顶点i的直接邻居节点j。

2. 迭代更新最短路径:- 对于每一个顶点k,在`dist`和`path`中进行更新。

- 遍历所有的i和j,如果从顶点i经过顶点k到达顶点j的路径长度小于当前记录的最短路径,则更新`dist[i][j]`和`path[i][j]`为新的最短路径长度和经过的顶点。

3. 返回最短路径:- 根据`path`数组,利用回溯算法获取任意两个顶点之间的最短路径。

下面我们通过一个例子来演示floyd法的实施步骤。

假设我们有以下带权有向图:1 3>(B)->/ 21// V(0) <2V V(A)>C3我们首先需要将图转化为邻接矩阵表示。

根据图中的边权重,我们得到以下邻接矩阵:A B CA 0 1 ∞B ∞0 3C 2 ∞0接下来,我们开始执行floyd法的步骤。

1. 初始化:- `dist`数组:A B CA 0 1 ∞B ∞0 3C 2 ∞0- `path`数组:A B CA -B -B - - CC A - -2. 迭代更新最短路径:- 首先,我们选取顶点A作为中间顶点,即`k=A`。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

求最短路径算法总结分类:数据结构标签:floyd算法it部分内容参考All-Pairs 的最短路径问题:所有点对之间的最短路径Dijkstra算法是求单源最短路径的,那如果求图中所有点对的最短路径的话则有以下两种解法:解法一:以图中的每个顶点作为源点,调用Dijkstra算法,时间复杂度为O(n3);解法二:Floyd(弗洛伊德算法)更简洁,算法复杂度仍为O(n3)。

n正如大多数教材中所讲到的,求单源点无负边最短路径用Dijkstra,而求所有点最短路径用Floyd。

确实,我们将用到Floyd算法,但是,并不是说所有情况下Floyd都是最佳选择。

对于没有学过Floyd的人来说,在掌握了Dijkstra之后遇到All-Pairs最短路径问题的第一反应可能会是:计算所有点的单源点最短路径,不就可以得到所有点的最短路径了吗。

简单得描述一下算法就是执行n次Dijkstra算法。

Floyd可以说是Warshall算法的扩展了,三个for循环便可以解决一个复杂的问题,应该说是十分经典的。

从它的三层循环可以看出,它的复杂度是n3,除了在第二层for中加点判断可以略微提高效率,几乎没有其他办法再减少它的复杂度。

比较两种算法,不难得出以下的结论:对于稀疏的图,采用n次Dijkstra比较出色,对于茂密的图,可以使用Floyd算法。

另外,Floyd可以处理带负边的图。

下面对Floyd算法进行介绍:Floyd算法的基本思想:可以将问题分解,先找出最短的距离,然后在考虑如何找出对应的行进路线。

如何找出最短路径呢,这里还是用到动态规划的知识,对于任何一个城市而言,i到j的最短距离不外乎存在经过i与j之间的k和不经过k两种可能,所以可以令k=1,2,3,...,n(n是城市的数目),在检查d(ij)与d(ik)+d(kj)的值;在此d(ik)与d(kj)分别是目前为止所知道的i到k 与k到j的最短距离,因此d(ik)+d(kj)就是i到j经过k的最短距离。

所以,若有d(ij)>d(ik)+d(kj),就表示从i出发经过k再到j的距离要比原来的i到j距离短,自然把i到j的d(ij)重写为d(ik)+d(kj),每当一个k查完了,d(ij)就是目前的i到j的最短距离。

重复这一过程,最后当查完所有的k时,d(ij)里面存放的就是i到j之间的最短距离了。

Floyd算法的基本步骤:定义n×n的方阵序列D-1, D0 , … Dn-1,初始化:D-1=CD-1[i][j]=边<i,j>的长度,表示初始的从i到j的最短路径长度,即它是从i到j的中间不经过其他中间点的最短路径。

迭代:设Dk-1已求出,如何得到Dk(0≤k≤n-1)?Dk-1[i][j]表示从i到j的中间点不大于k-1的最短路径p:i…j,考虑将顶点k加入路径p得到顶点序列q:i…k…j,若q不是路径,则当前的最短路径仍是上一步结果:Dk[i][j]= Dk-1[i][j];否则若q的长度小于p的长度,则用q取代p作为从i到j的最短路径。

因为q的两条子路径i…k和k…j皆是中间点不大于k-1的最短路径,所以从i到j中间点不大于k的最短路径长度为:Dk[i][j]=min{ Dk-1[i][j], Dk-1[i][k] +Dk-1[k][j] }Floyd算法实现:可以用三个for循环把问题搞定了,但是有一个问题需要注意,那就是for循环的嵌套的顺序:我们可能随手就会写出这样的程序,但是仔细考虑的话,会发现是有问题的。

for(int i=0; i<n; i++)for(int j=0; j<n; j++)for(int k=0; k<n; k++)问题出在我们太早的把i-k-j的距离确定下来了,假设一旦找到了i-p-j最短的距离后,i 到j就相当处理完了,以后不会在改变了,一旦以后有使i到j的更短的距离时也不能再去更新了,所以结果一定是不对的。

所以应当象下面一样来写程序:for(int k=0; k<n; k++)for(int i=0; i<n; i++)for(int j=0; j<n; j++)这样作的意义在于固定了k,把所有i到j而经过k的距离找出来,然后象开头所提到的那样进行比较和重写,因为k是在最外层的,所以会把所有的i到j都处理完后,才会移动到下一个k,这样就不会有问题了,看来多层循环的时候,我们一定要当心,否则很容易就弄错了。

接下来就要看一看如何找出最短路径所行经的城市了,这里要用到另一个矩阵P,它的定义是这样的:p(ij)的值如果为p,就表示i到j的最短行经为i->...->p->j,也就是说p是i 到j的最短行径中的j之前的最后一个城市。

P矩阵的初值为p(ij)=i。

有了这个矩阵之后,要找最短路径就轻而易举了。

对于i到j而言找出p(ij),令为p,就知道了路径i->...->p->j;再去找p(ip),如果值为q,i到p的最短路径为i->...->q->p;再去找p(iq),如果值为r,i到q的最短路径为i->...->r->q;所以一再反复,到了某个p(it)的值为i时,就表示i到t的最短路径为i->t,就会的到答案了,i到j的最短行径为i->t->...->q->p->j。

因为上述的算法是从终点到起点的顺序找出来的,所以输出的时候要把它倒过来。

但是,如何动态的回填P矩阵的值呢?回想一下,当d(ij)>d(ik)+d(kj)时,就要让i到j 的最短路径改为走i->...->k->...->j这一条路,但是d(kj)的值是已知的,换句话说,就是k->...->j 这条路是已知的,所以k->...->j这条路上j的上一个城市(即p(kj))也是已知的,当然,因为要改走i->...->k->...->j这一条路,j的上一个城市正好是p(kj)。

所以一旦发现d(ij)>d(ik)+d(kj),就把p(kj)存入p(ij)。

下面是具体的C代码:#include <stdio.h>#include <limits.h>#include <stdlib.h>#define MAXSIZE 20void floyd(int [][MAXSIZE], int [][MAXSIZE], int);void display_path(int [][MAXSIZE], int [][MAXSIZE], int);void reverse(int [], int);void readin(int [][MAXSIZE], int *);#define MAXSUM(a, b) (((a) != INT_MAX && (b) != INT_MAX) ? \((a) + (b)) : INT_MAX)void floyd(int dist[][MAXSIZE], int path[][MAXSIZE], int n){int i, j, k;for (i = 0; i < n; i++)for (j = 0; j < n; j++)path[i][j] = i;for (k = 0; k < n; k++)for (i = 0; i < n; i++)for (j = 0; j < n; j++)if (dist[i][j] > MAXSUM(dist[i][k], dist[k][j])){path[i][j] = path[k][j];dist[i][j] = MAXSUM(dist[i][k], dist[k][j]);}}void display_path(int dist[][MAXSIZE], int path[][MAXSIZE], int n) {int *chain;int count;int i, j, k;printf("\n\nOrigin->Dest Dist Path");printf( "\n-----------------------------");chain = (int *) malloc(sizeof(int)*n);for (i = 0; i < n; i++)for (j = 0; j < n; j++){if (i != j){printf("\n%6d->%d ", i+1, j+1);if (dist[i][j] == INT_MAX)printf(" NA ");else{printf("%4d ", dist[i][j]);count = 0;k = j;do{k = chain[count++] = path[i][k];} while (i != k);reverse(chain, count);printf("%d", chain[0]+1);for (k = 1; k < count; k++)printf("->%d", chain[k]+1);printf("->%d", j+1);}}}free(chain);}#define SWAP(a, b) { temp = a; a = b; b = temp; } void reverse(int x[], int n){int i, j, temp;for (i = 0, j = n-1; i < j; i++, j--)SW AP(x[i], x[j]);}void readin(int dist[][MAXSIZE], int *number){int origin, dest, length, n;int i, j;char line[100];gets(line);sscanf(line, "%d", &n);*number = n;for (i = 0; i < n; i++){for (j = 0; j < n; j++)dist[i][j] = INT_MAX;dist[i][i] = 0;}gets(line);sscanf(line, "%d%d%d", &origin, &dest, &length);while (origin != 0 && dest != 0 && length != 0){dist[origin-1][dest-1] = length;gets(line);sscanf(line, "%d%d%d", &origin, &dest, &length);}}/// 测试程序如下所示:int main(void){int dist[MAXSIZE][MAXSIZE];int path[MAXSIZE][MAXSIZE];int n;printf("\nInput the path information:");printf("\n----------------------------\n");readin(dist, &n);floyd(dist, path, n);display_path(dist, path, n);getchar();}其中readin函数规定了输入的格式,第一列是指出有多少个城市;第二列以后每行三个数;第一个和第二个是一条路径的起点和终点,第三个数是路径的长度,最后以三个0作为输入结束条件。

相关文档
最新文档