搜索与图论 - floyd 算法

简介: 搜索与图论 - floyd 算法

文章目录


一、floyd 算法

1. floyd 算法简介

2. floyd 算法核心思想

3. floyd 算法实现步骤

4. floyd 算法具体实现详见例题 floyd 求最短路。

二、floyd 算法与其他算法的总结复习(重点)

1. Dijkstra 算法-朴素 O(n*n)

2. Dijkstra 算法-堆优化 O(mlogm)

3. Bellman-ford 算法 O(nm)

4. spfa 算法 O(n)~O(nm)

5. floyd 算法 O(n*n*n)

三、floyd 算法例题—— floyd 求最短路

具体实现

1. 样例演示

2. 实现思路

3. 代码注解

4. 实现代码


一、floyd 算法

1. floyd 算法简介



floyd 算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与 Dijkstra 算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。

floyd 算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路径的算法。

floyd 算法的单个执行将找到所有顶点对之间的最短路径的长度(加权)。 虽然它不返回路径本身的细节,但是可以通过对算法的简单修改来重建路径。

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

缺点:时间复杂度比较高,不适合计算大量数据。


2. floyd 算法核心思想


(1) 邻接矩阵(二维数组)dist 储存路径,数组中的值开始表示节点和节点之间初始直接路径,最终是节点和节点之间的最小路径,有两点需要注意的,第一是如果没有直接相连的两点那么默认为一个很大的值(不要因为计算溢出成负数),第二是自己和自己的距离要为 0。

(2) 从第 1 个到第 n 个点依次加入松弛计算,每个点加入进行试探枚举是否有路径长度被更改(自己能否更新路径)。顺序加入( k 枚举)松弛的点时候,需要遍历图中每一个点对( i , j )双重循环),判断每一个点对距离是否因为加入的点而发生最小距离变化,如果发生改变(变小),那么两点( i , j )距离就更改。

(3) 重复上述直到最后插点试探完成。

其中第 2 步的状态转移方程为:


dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);

其中 dp[a][b] 的意思可以理解为节点 a 到节点 b 的最短路径,所以 dp[i][k] 的意思可以理解为节点 i 到节点 k 的最短路径, dp[k][j] 的意思为节点 k 到节点 j 的最短路径。


3. floyd 算法实现步骤


  • (1) 在主函数中创建一个矩阵,存储输入的两点间的距离。
  • (2) 在 floyd 函数中,初始化记录最短距离的矩阵和记录中介点的矩阵。初始化之后将主函数的矩阵复制给记录最短距离的矩阵。
  • (3) 用三层循环不断更新最短距离。


4. floyd 算法具体实现详见例题 floyd 求最短路。

二、floyd 算法与其他算法的总结复习(重点)


8730e5065659486aa4289933e789ec91.png


1. Dijkstra 算法-朴素 O(n*n)


(1) 初始化距离数组, dist[1] = 0, dist[i] = 0x3f3f3f3f。

(2) for n 次循环 每次循环确定一个 min 加入 S 集合中,n 次之后就得出所有的最短距离。

(3) 将不在 S 中 dist_min 的点 ->t。

(4) t->S 加入最短路集合。

(5) 用 t 更新到其他点的距离


2. Dijkstra 算法-堆优化 O(mlogm)


  • (1) 利用邻接表,优先队列。
  • (2) 在 priority_queue<PII,vector,greater> heap; 中将返回堆顶。
  • (3) 利用堆顶来更新其他点,并加入堆中类似广度优先搜索。


3. Bellman-ford 算法 O(nm)


  • (1) 注意连锁想象需要备份,struct Edge{inta,b,c} Edge[M]。
  • (2) 初始化 dist, 松弛 dist[x.b] = min(dist[x.b], backup[x.a]+x.w)。
  • (3) 松弛 k 次,每次访问 m 条边。


4. spfa 算法 O(n)~O(nm)


  • (1) 利用队列优化仅加入修改过的地方。
  • (2) for k 次。
  • (3) for 所有边利用宽搜模型去优化 bellman-ford 算法。
  • (4) 更新队列中当前点的所有出边。


5. floyd 算法 O(nnn)

  • (1) 初始化 d 。
  • (2) k,i,j 去更新 d 。


三、floyd 算法例题—— floyd 求最短路

题目描述


给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,边权可能为负数。

再给定 k 个询问,每个询问包含两个整数 x 和 y,表示查询从点 x 到点 y 的最短距离,如果路径不存在,则输出 impossible

数据保证图中不存在负权回路。


输入格式

第一行包含三个整数 n,m,k。

接下来 m 行,每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。

接下来 k 行,每行包含两个整数 x,y,表示询问点 x 到点 y 的最短距离。

输出格式


共 k 行,每行输出一个整数,表示询问的结果,若询问两点间不存在路径,则输出 impossible

数据范围

1 ≤ n ≤ 200

1 ≤ k ≤ n2

1 ≤ m ≤ 20000

图中涉及边长绝对值均不超过 10000。


输入样例

3 3 2

1 2 1

2 3 2

1 3 1

2 1

1 3

输出样例

impossible

1


具体实现

1. 样例演示


首先,输入 n=3,m=3,k=2;表示图有 3 个点,3 条边,询问 2 次。

第一条边是从节点 1 到节点 2 ,边长为 1。

第二条边是从节点 2 到节点 3 ,边长为 2。

第三条边是从节点 1 到节点 3 ,边长为 1。

第一次询问,节点 2 到节点 1 是否存在路径?

第二次询问,节点 1 到节点 3 是否存在路径?

显然,第一次询问结果 impossible。

第二次询问结果 1。


2. 实现思路

  • 详见上文核心思想和实现步骤


3. 代码注解

  • floyd 本身是floyd 本身是个动态规划算法,在代码实现的时候省去了一维状态。

原状态是:f[i, j, k]表示从 i 走到 j 的路径上除了 i , j 以外不包含点 k 的所有路径的最短距离。那么f[i, j, k] = min(f[i, j, k - 1), f[i, k, k - 1] + f[k, j, k - 1]。

因此在计算第 k 层的 f[i, j] 的时候必须先将第 k - 1 层的所有状态计算出来,所以需要把 k 放在最外层。


4. 实现代码

#include <bits/stdc++.h>
using namespace std;
const int N = 210, INF = 1e9;
int n, m, Q;
int d[N][N];
void floyd()
{
    for (int k = 1; k <= n; k ++ )
    {
        for (int i = 1; i <= n; i ++ )
        {
            for (int j = 1; j <= n; j ++ )
            {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
}
int main()
{
    cin >> n >> m >> Q;
    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j <= n; j ++ )
        {
            if (i == j) 
            {
                d[i][j] = 0;
            }
            else 
            {
                d[i][j] = INF;
            }
        }
    }
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = min(d[a][b], c);
    }
    floyd();
    while (Q -- )
    {
        int a, b;
        cin >> a >> b;
        int t = d[a][b];
        if (t > INF / 2) 
        {
            puts("impossible");
        }
        else 
        {
            cout << t << endl;
        }
    }
    system("pause");
    return 0;
}



























目录
打赏
0
0
0
0
2
分享
相关文章
基于和声搜索优化算法的机器工作调度matlab仿真,输出甘特图
本程序基于和声搜索优化算法(Harmony Search, HS),实现机器工作调度的MATLAB仿真,输出甘特图展示调度结果。算法通过模拟音乐家即兴演奏寻找最佳和声的过程,优化任务在不同机器上的执行顺序,以最小化完成时间和最大化资源利用率为目标。程序适用于MATLAB 2022A版本,运行后无水印。核心参数包括和声记忆大小(HMS)等,适应度函数用于建模优化目标。附带完整代码与运行结果展示。
算法系列之搜索算法-深度优先搜索DFS
深度优先搜索和广度优先搜索一样,都是对图进行搜索的算法,目的也都是从起点开始搜索,直到到达顶点。深度优先搜索会沿着一条路径不断的往下搜索,直到不能够在继续为止,然后在折返,开始搜索下一条候补路径。
118 62
算法系列之搜索算法-深度优先搜索DFS
阿里云 AI 搜索开放平台:从算法到业务——AI 搜索驱动企业智能化升级
本文介绍了阿里云 AI 搜索开放平台的技术的特点及其在各行业的应用。
|
2月前
|
算法系列之搜索算法-广度优先搜索BFS
广度优先搜索(BFS)是一种非常强大的算法,特别适用于解决最短路径、层次遍历和连通性问题。在面试中,掌握BFS的基本实现和应用场景,能够帮助你高效解决许多与图或树相关的问题。
88 1
算法系列之搜索算法-广度优先搜索BFS
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量(通俗易懂版)
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量(通俗易懂版)
【狂热算法篇】探秘图论之 Floyd 算法:解锁最短路径的神秘密码(通俗易懂版)
【狂热算法篇】探秘图论之 Floyd 算法:解锁最短路径的神秘密码(通俗易懂版)
基于免疫算法的最优物流仓储点选址方案MATLAB仿真
本程序基于免疫算法实现物流仓储点选址优化,并通过MATLAB 2022A仿真展示结果。核心代码包括收敛曲线绘制、最优派送路线规划及可视化。算法模拟生物免疫系统,通过多样性生成、亲和力评价、选择、克隆、变异和抑制机制,高效搜索最优解。解决了物流仓储点选址这一复杂多目标优化问题,显著提升物流效率与服务质量。附完整无水印运行结果图示。
基于免疫算法的最优物流仓储点选址方案MATLAB仿真
基于GA遗传优化TCN-GRU时间卷积神经网络时间序列预测算法matlab仿真
本项目基于MATLAB2022a开发,提供无水印算法运行效果预览及核心程序(含详细中文注释与操作视频)。通过结合时间卷积神经网络(TCN)和遗传算法(GA),实现复杂非线性时间序列的高精度预测。TCN利用因果卷积层与残差连接提取时间特征,GA优化超参数(如卷积核大小、层数等),显著提升模型性能。项目涵盖理论概述、程序代码及完整实现流程,适用于金融、气象、工业等领域的时间序列预测任务。
基于遗传优化算法的多AGV栅格地图路径规划matlab仿真
本程序基于遗传优化算法实现多AGV栅格地图路径规划的MATLAB仿真(测试版本:MATLAB2022A)。支持单个及多个AGV路径规划,输出路径结果与收敛曲线。核心程序代码完整,无水印。算法适用于现代工业与物流场景,通过模拟自然进化机制(选择、交叉、变异)解决复杂环境下的路径优化问题,有效提升效率并避免碰撞。适合学习研究多AGV系统路径规划技术。
基于GA遗传算法的斜拉桥静载试验车辆最优布载matlab仿真
本程序基于遗传算法(GA)实现斜拉桥静载试验车辆最优布载的MATLAB仿真,旨在自动化确定车辆位置以满足加载效率ηq(0.95≤ηq≤1.05)的要求,目标是使ηq尽量接近1,同时减少加载车辆数量和布载耗时。程序通过迭代优化计算车辆位置、方向、类型及占用车道等参数,并展示适应度值收敛过程。测试版本为MATLAB2022A,包含核心代码与运行结果展示。优化模型综合考虑车辆总重量、间距及桥梁允许载荷密度等约束条件,确保布载方案科学合理。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等