搜索与图论 - 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;
}



























相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
92 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
1月前
|
算法 搜索推荐 数据库
二分搜索:高效的查找算法
【10月更文挑战第29天】通过对二分搜索的深入研究和应用,我们可以不断挖掘其潜力,为各种复杂问题提供高效的解决方案。相信在未来的科技发展中,二分搜索将继续发挥着重要的作用,为我们的生活和工作带来更多的便利和创新。
50 1
|
29天前
|
JSON 算法 数据挖掘
基于图论算法有向图PageRank与无向图Louvain算法构建指令的方式方法 用于支撑qwen agent中的统计相关组件
利用图序列进行数据解读,主要包括节点序列分析、边序列分析以及结合节点和边序列的综合分析。节点序列分析涉及节点度分析(如入度、出度、度中心性)、节点属性分析(如品牌、价格等属性的分布与聚类)、节点标签分析(如不同标签的分布及标签间的关联)。边序列分析则关注边的权重分析(如关联强度)、边的类型分析(如管理、协作等关系)及路径分析(如最短路径计算)。结合节点和边序列的分析,如子图挖掘和图的动态分析,可以帮助深入理解图的结构和功能。例如,通过子图挖掘可以发现具有特定结构的子图,而图的动态分析则能揭示图随时间的变化趋势。这些分析方法结合使用,能够从多个角度全面解读图谱数据,为决策提供有力支持。
|
2月前
|
算法 决策智能
基于禁忌搜索算法的VRP问题求解matlab仿真,带GUI界面,可设置参数
该程序基于禁忌搜索算法求解车辆路径问题(VRP),使用MATLAB2022a版本实现,并带有GUI界面。用户可通过界面设置参数并查看结果。禁忌搜索算法通过迭代改进当前解,并利用记忆机制避免陷入局部最优。程序包含初始化、定义邻域结构、设置禁忌列表等步骤,最终输出最优路径和相关数据图表。
|
2月前
|
存储 算法 C++
弗洛伊德(Floyd)算法(C/C++)
弗洛伊德(Floyd)算法(C/C++)
|
2月前
|
存储 算法 C++
【搜索算法】 跳马问题(C/C++)
【搜索算法】 跳马问题(C/C++)
|
2月前
|
人工智能 算法 Java
【搜索算法】数字游戏(C/C++)
【搜索算法】数字游戏(C/C++)
|
19天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。
|
25天前
|
机器学习/深度学习 算法 Serverless
基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM
本项目利用鲸鱼优化算法(WOA)优化支持向量机(SVM)参数,针对乳腺癌早期诊断问题,通过MATLAB 2022a实现。核心代码包括参数初始化、目标函数计算、位置更新等步骤,并附有详细中文注释及操作视频。实验结果显示,WOA-SVM在提高分类精度和泛化能力方面表现出色,为乳腺癌的早期诊断提供了有效的技术支持。
|
5天前
|
供应链 算法 调度
排队算法的matlab仿真,带GUI界面
该程序使用MATLAB 2022A版本实现排队算法的仿真,并带有GUI界面。程序支持单队列单服务台、单队列多服务台和多队列多服务台三种排队方式。核心函数`func_mms2`通过模拟到达时间和服务时间,计算阻塞率和利用率。排队论研究系统中顾客和服务台的交互行为,广泛应用于通信网络、生产调度和服务行业等领域,旨在优化系统性能,减少等待时间,提高资源利用率。