最短路径问题——floyd算法
Floyd算法是一种动态规划算法,用于求解带权图中所有顶点对之间的最短路径。其核心思想是通过三重循环逐步更新距离矩阵,允许处理负权边(不含负权环)。优点是实现简单,能直接计算全局解;缺点是O(n³)时间复杂度和O(n²)空间复杂度使其不适合大规模图。适用于稠密图、存在负权边或需要频繁查询任意两点最短路径的场景。算法通过不断添加中转点(k)来优化路径:若i经k到j的路径更短,则更新距离矩阵e[i][
Floyd算法(Floyd-Warshall算法)是一种用于求解所有顶点对之间最短路径的动态规划算法,适用于带权有向图或无向图(允许负权边,但不含负权环)。
优缺点及适用性
优点
-
全局最优解
直接计算出图中任意两个顶点之间的最短路径,而不仅针对单一源点。 -
代码实现简单
核心算法仅需三重循环,逻辑清晰(动态规划思想),易于编写。 -
处理负权边
允许图中存在负权边(只要没有负权环),而Dijkstra算法无法处理这种情况。 -
无重复计算
通过动态规划表(距离矩阵)逐步优化,避免重复计算子问题。 -
适用于稠密图
在稠密图(边数接近顶点数平方)中,性能可能优于多次调用Dijkstra或Bellman-Ford。
缺点
-
时间复杂度高
时间复杂度为 O(n3)(n为顶点数),在稀疏图或大规模图中效率较低。例如,对于1,000个顶点的图,需执行10亿次操作。 -
空间复杂度高
需维护 n×n 的距离矩阵,空间复杂度为 O(n2),对内存消耗较大。 -
无法处理负权环
如果图中存在负权环,算法无法得到正确结果(但可检测出负权环的存在)。 -
不适用动态图
每次图结构变化(如增删边)时,需重新计算整个矩阵,无法高效增量更新。 -
常数因子较大
使理论复杂度与矩阵乘法相当,实际运行常数较大,对小规模图可能不如Dijkstra高效。
适用场景
-
小规模图(顶点数较少)或稠密图。
-
需要频繁查询任意两点间最短路径的场景。
-
图中存在负权边(但无负权环)。
总结
floyd算法编码简单(只需要三重for循环),但时间复杂度较大,无法处理大规模图。
使用方法
例如下图,我们有1~4四个顶点,不同顶点之间有不同的带权路径,现在要求解任意两个顶点之间的最短路径的权值。那么应该怎么做呢?

首先,我们可以将有向图转化为更加简便的表格,如下:

该表中每个点到其本身的距离为0,没有单向边直接连通的两个点之间距离为无穷大。
对于两个初始点之间的距离(1->2),如果存在第三个点(3)(中转点),使得这个中转点加进来之后,总距离变短了,那么我们可以知道这个中转点可以使两个初始点之间形成更短路径(1->3->2)。以此类推,如果存在第k个中转点,加进两个初始点之间,可以使总距离变短,那么第k个中转点可以使两个初始点之间形成更短路径(1->…->k->…->2)。当所有合法的中转点全部加到两个初始点之间后,所形成的路径便是最短路径。这个就是floyd算法的核心思路。
下面我们开始演示:
首先,我们先将所有顶点之间的距离存入一个二维数组e[i][j]。
之后,我们先将一号顶点作为中转点,如果其余两点间的距离比其中一点到1再到另一点的距离大,那么一号中转点的加入可以使两点之间的距离变短,我们就更新一下两点之间的数据。
代码如下:
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(e[i][j]>e[i][1]+e[1][j])
{
e[i][j]=e[i][1]+e[1][j];
}
}
}
更新之后的表格如下图所示:(绿色的表示更新后的距离)

以此类推,将二号点、三号点……k号点全部作为中转点循环一遍之后,我们就得出了任意两点之间的最短路径的权值,也就是最短距离。在后续的步骤中,我们通过访问e[i][j]的数据,即可得到任意两点之间的最短距离。
核心代码如下:
for(k=1;k<=n;k++)//依次经过1~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];
}
}
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)