Floyd算法学习笔记

news2024/9/27 19:22:01

Floyd算法学习笔记

前言

同步于 c n b l o g s cnblogs cnblogs 发布

如有错误,欢迎各位 dalao 批评指出。

前置芝士:

1.邻接矩阵(Floyd要用邻接矩阵存图)

2.动态规划思想(最好学过,没学过也没有太大影响)

1. Floyd 所解决问题的类型

我们可以发现,如 Dijkstra,SPFA,Bellman Ford 一类的最短路算法都是解决单源点最短路问题,也就是确定了起点或者终点来求最短路的问题。但是,我们发现,这些算法解决多源点最短路问题,也就是有多个起点和终点的最短路问题 ,的效率太低。假设有 n n n 个点, m m m 条边。解决多源最短路时,如果用以上三种算法来解决,都需要分别做 n n n 次,来求解以每个点为起点的单源最短路,时间复杂度最慢分别是 O ( n m l o g n ) , O ( n 2 m ) , O ( n 2 m ) O(nmlogn),O(n^2m),O(n^2m) O(nmlogn),O(n2m),O(n2m),在稠密图 m = n ∗ ( n − 1 ) / 2 ≈ n 2 m=n*(n-1)/2≈n^2 m=n(n1)/2n2其中最快的都需要 O ( n 3 l o g m ) O(n^3logm) O(n3logm) ,最慢的甚至是 O ( n 4 ) O(n^4) O(n4) ,效率太低。因此,我们今天的主角 Floyd 就因解决多源最短路问题而诞生了!

2. Floyd 的思想和基本做法

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

d p i j dp_{ij} dpij 表示 i i i j j j 的最短距离。(有 n n n 个点)

首先对于这个 d p dp dp 数组的初始化就是将输入的边 x − y x-y xy 权值为 z z z (无权图就是 1 1 1),如果图是无向,则 d p x y = d p y x = z dp_{xy}=dp_{yx}=z dpxy=dpyx=z ,如果图是有向,则 d p x y = z dp_{xy}=z dpxy=z,最后将所有 d p i i = 0 ( 0 ≤ i ≤ n ) dp_{ii}=0 (0\le i\le n) dpii=0(0in),比较显然,这里不做解释。

接着我们进行状态转移。显然,我们要转移 d p i j dp_{ij} dpij,就需要找一个点 k k k,来进行转移,也就是 d p i j ← m i n ( d p i j , d p i k + d p k j ) dp_{ij}\gets min(dp_{ij},dp_{ik}+dp_{kj}) dpijmin(dpij,dpik+dpkj),其中 d p i k + d p k j dp_{ik}+dp_{kj} dpik+dpkj 就表示 i − k i-k ik 的最短路与 j − k j-k jk 的最短路之和,其实也就相当于一个松弛操作。

这里特别要注意的是:我们的 k k k 那一层循环一定要放在 i i i j j j 两层循环之外,因为如果放在 i , j i,j i,j 以内的话,你就会发现每两个点的最短路只会被算到一次,而当你在进行状态转移时,你只算到一次的话,你会发现有些点在转移时,还没有被更新,就会出现没有求出最短路的情况,所以, k k k 的循环要放到 i , j i,j i,j 的循环之外。

Floyd算法由于 i , j , k i,j,k i,j,k 都要枚举一层循环,所以时间复杂度为 O ( n 3 ) O(n^3) O(n3),比开头讲的三个算法要快。

3.Floyd 代码实现

//n表示有n个点 
memset(dp,0x3f,sizeof(dp));//赋一个极大值,并且防止在转移时不溢出。
//接下来进行边的初始化和dp[i][i]=0
............
//状态转移 
for(int k=1;k<=n;++k)//枚举k 
{
	for(int i=1;i<=n;++i)//枚举i 
	{
		if(i==k)//如果i,k个点相等,则不需要更新 
		continue;
		for(int j=1;j<=n;++j)
		{
			if(i==j||k==j)//同第八行 
			continue;
			dp[i][j]=min(dp[i][k]+dp[k][j],dp[i][j]);//状态转移。 
		}
	}
}

4.Floyd 算法的一些其他应用

(1).Floyd 输出路径

对于输出路径,我们可以定义一个 p a t h i j path_{ij} pathij 表示 d p i j dp_{ij} dpij 是有 d p i p a t h i j + d p p a t h i j j dp_{ipath_{ij}}+dp_{path_{ij}j} dpipathij+dppathijj 转移而来。并且在一开始,我们将所有 p a t h path path 数组的元素赋一个特殊值。(假定为 − 1 -1 1 )

显然,要输出 i − j i-j ij 的路径,我们可以通过递归来解决。

具体代码如下:

//赋特殊值并且做 floyd
-----------
//输出路径函数
void print(int i,int j)//print(a,b) 表示输出a,b的最短路径
{
    if(path[i][j]==-1)//因为开始初始化为-1,这里就可以避免相邻的再次输出 
        return;
    print(i,path[i][j]);//前半部分
    cout<<path[i][j]<<"-->";//输出该点 
    print(path[i][j],j);//后半部分
}

(2).Floyd 判断负环

在说这一个应用之前,我们先来讲一下负环的定义。

负环,就是指一个图中,存在一个环,使得这个环的权值之和为负数,这个环就是负环。

例如下图:

qwq

可以发现,由图中三个点组成的一个环的权值之和为负数,这就是一个简单的负环。

一个图中一旦存在负环,环里的两个点之间的最短路可以被无限更新,因为为了使得路径长度最短,它可以一直走这个负环,无限循环,这个最短路径就可以无限缩小。也就是说,一个图一旦存在负环,它的最短路就是 − ∞ -\infty ,也就相当于无解。

虽然说 SPFA Bellmanford 两个最短路算法可以判断负环,但是我们还是要讲一讲 Floyd 算法判断负环的方法。

因为负环可以使得两个点之间的最短路无限变小,所以我们可以发现,我们可以做两次 Floyd ,第一次来更新所谓的最短路,然后再做第二次的时候,如果两个点之间的最短路还可以被更新,就可以说明这个图中存在负环,比较显然。(自己想一想)。

第二次 Floyd 代码实现:

for(int k=1;k<=n;++k)
{
    for(int i=1;i<=n;++i)
    {
        if(i==k)//同第一次
        continue;
        for(int j=1;j<=n;++j)
        {
            if(i==j||j==k)//同上
            continue;
            if(dp[i][j]>dp[i][k]+dp[k][j])//如果可以被更新,则存在负环
            {
                puts("No solution!");
            }
        }
    }
}

(3).Floyd 判断有向图的连通性

我们知道,对于无向图的两个点是否联通,我们可以运用并查集来判断两个点是否联通。

但是对于一个有向图,并查集是不能够维护的,所以这个时候,我们就再一次请出今天的主角 Floyd 来判断两个点 i , j i,j i,j 是否连通。

我们定义 d p i j dp{ij} dpij 表示 i , j i,j i,j 是否连通,若联通则为 1 1 1 ,不连通则为 0 0 0

显然,我们可以根据 Floyd 一一样的方式进行初始化。一开始除了 d p i i dp_{ii} dpii 全部赋值为 0 0 0 ,输入边的时候直接初始化即可。

接下来就是状态转移。我们可以模仿普通的 Floyd ,再找一个点 k k k ,如果 i i i 可以到达 k k k , k k k 可以到达 j j j ,就可以说明 i i i 可以到达 j j j ,转化成转移方程就是 d p i j ∣ = d p i k & d p k j dp_{ij}|=dp_{ik}\&dp_{kj} dpij=dpik&dpkj

核心代码:

//n表示有n个点 
memset(dp,0,sizeof(dp));//赋值。
//接下来进行边的初始化和dp[i][i]=1
............
//状态转移 
for(int k=1;k<=n;++k)//枚举k 
{
	for(int i=1;i<=n;++i)//枚举i 
	{
		if(i==k)//同上
		continue;
		for(int j=1;j<=n;++j)
		{
			if(i==j||k==j)//同上
			continue;
			dp[i][j]|=dp[i][k]&dp[k][j];//状态转移。 
		}
	}
}

关于 Floyd 算法的讲解就到这里了, s e e   y o u see~ you see you

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/731077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无线视频传输方案|远距离无人机图传应用,+28dBm大功率wifi图传模块

针对无人机远程图片、视频传输需求&#xff0c;市面上就有无线模块研发厂家推出了基于大功率图传WiFi模块SKW77的无人机远程视频传输解决方案。在无人机和地面的中继器内加入串口WiFi模块&#xff0c;手机通过与无人机和地面的中继器内置的串口WiFi模块给无人机传递控制信号&am…

深度理解 JAVA 动态代理

本文篇幅比较长&#xff0c;在确定您是否需要仔细阅读本文前&#xff0c;可以先思考一下下面几个问题&#xff1a; 动态代理是什么&#xff1f;如何实现动态代理&#xff1f;所有类都能实现动态代理吗&#xff1f;非目标方法是否会被代理&#xff1f;为什么 JDK 实现动态代理必…

平安养老险广东分公司积极开展“7·8全国保险公众宣传日”系列活动

2023年是全面贯彻落实党的二十大精神的开局之年&#xff0c;是实施“十四五”规划承上启下的关键之年。在国家金融监督管理总局指导、中国保险行业协会组织下&#xff0c;平安养老保险股份有限公司广东分公司&#xff08;以下简称“平安养老险广东分公司”&#xff09;以“78全…

ETHERNET/IP转MODBUS-RTU协议网关

远创智控YC-EIP-RTU是自主研发的一款ETHERNET/IP从站功能的通讯网关。该产品主要功能是将各种MODBUS-RTU设备接入到ETHERNET/IP网络中。 远创智控YC-EIP-RTU连接到ETHERNET/IP总线中做为从站使用&#xff0c;连接到MODBUS-RTU总线中做为主站或从站使用。 2.ETHERNET/IP转MODBU…

IDEA中配置Java反编译工具javap -c

IDEA中配置Java反编译工具javap -c 一、前置条件二、新建外部工具三、使用方式 欢迎访问我的个人博客&#xff1a;https://wk-blog.vip 一、前置条件 确保 IDEA 已经开启了编译 javac 。默认 IDEA 是开启的。 二、新建外部工具 首先进入 Settings ---> Tools ---> Ext…

自动化测试报告样式HTMLTestRunner、BeautifulReport、HTMLReport、Allure你喜欢哪个?

自动化测试报告样式HTMLTestRunner、BeautifulReport、HTMLReport、Allure你喜欢哪个&#xff1f; 1 框架设计(准备工作)1.1 简易框架图1.2 common/reportOut.py1.3 report1.4 testcase/test_baidu.py1.5 mian.py 2 HTMLTestRunner2.1 下载使用2.2 reportOut.py设计2.3 报告样式…

十一、框架与大数据模型

frameset标签 1、frameset标签 这种结构&#xff0c;基本上被淘汰 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <frameset cols"25%,75%">&…

统计每列中不同值出现的次数.apply(pd.value_counts)

在Python 的pandas.DataFrame中有一种操作&#xff0c;它可以大大减轻我们的工作量&#xff0c;方便我们更快地进行数据分析&#xff0c;加快处理工作的效率。这就是 .apply(pd.value_counts) pandas 的强大&#xff0c;越使用&#xff0c;也就越爱了。现在就来夸夸它的作用啦…

统计学习导论(ISLR) 第八章树模型课后习题

统计学习导论(ISLR) 第八章树模型课后习题 🌸个人主页:JOJO数据科学📝个人介绍:统计学top3高校统计学硕士在读💌如果文章对你有帮助,欢迎✌关注、👍点赞、✌收藏、👍订阅专栏✨本文收录于【R语言数据科学】本系列主要介绍R语言在数据科学领域的应用包括: R语言…

二叉树 — 返回最大的二叉搜索子树大小

题目&#xff1a; 给定一棵二叉树的head节点&#xff0c;返回这颗二叉树中最大的二叉搜索子树的大小。 一颗二叉树来讲&#xff0c;可能整棵树不是搜索二叉树&#xff0c;但子树是一颗搜索二叉树。如下图所示&#xff0c;这时要返回这颗子搜索二叉树的最大节点个数。下图中&…

【node报错】cannot be loaded because running scripts is disabled on this system.

了解意思&#xff1a; cannot be loaded because running scripts is disabled on this system. 因为在该系统上禁用了运行脚本&#xff1b; 这个错误是由于你的系统执行策略&#xff08;Execution Policies&#xff09;禁止运行脚本导致的。Windows 系统默认情况下禁止运行…

ChatGPT前身GPT的论文-译文

写在前面 论文 Improving Language Understanding by Generative Pre-Training 地址 https://www.cs.ubc.ca/~amuham01/LING530/papers/radford2018improving.pdf ChatGPT火了&#xff0c;改论文作为ChatGPT的前身&#xff0c;可以从这里看到ChatGPT的原始影子。 摘要 自然语言…

制造业怎么应用大数据?_光点科技

随着信息技术的迅猛发展&#xff0c;大数据正逐渐成为各行各业的重要资源和工具。在制造业中&#xff0c;大数据的应用也逐渐得到了广泛关注。 制造业如何应用大数据&#xff1f; 首先&#xff0c;数据采集是制造业应用大数据的重要一环。制造业的生产过程中涉及到大量的数据&a…

二叉树OJ题:LeetCode--101.对称二叉树

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下LeetCode中第144道二叉树OJ题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个 人…

49天精通Java,第0天,编程语言类型有哪些?我心中的TOP1编程语言,什么是java跨平台性?

目录 一、常见的编程语言类型1、机器语言2、汇编语言3、高级语言 二、计算机编程语言三、跨平台性1、跨平台的优势包括&#xff1a;2、实现跨平台的方式包括&#xff1a; 四、Java的跨平台性五、java运行时和虚拟机六、Java内存管理和Java垃圾回收1、Java内存管理2、Java垃圾回…

基于matlab使用虚幻引擎模拟开发视觉SLAM算法(附源码)

一、前言 本示例展示了如何使用从虚幻引擎模拟环境中获取的图像数据开发可视化同步定位和映射&#xff08;SLAM&#xff09;算法。 视觉SLAM是计算摄像机相对于周围环境的位置和方向&#xff0c;同时映射环境的过程。开发可视化 SLAM 算法并评估其在不同条件下的性能是一项具…

抖音短视频矩阵管理系统源码开发部署(开源定制)

一、什么是短视频矩阵管理系统&#xff1f; 短视频矩阵管理系统是专门为企业号商家、普通号商家提供帐号运营从流量 到转化成交的一站式服务方案&#xff0c;具体包含&#xff1a;点赞关注评论主动私信 &#xff0c;评论区回复&#xff0c;自动潜客户挖掘&#xff0c;矩阵号营销…

今日小课堂:会议录音转文字怎么弄的

小君&#xff1a;嘿&#xff0c;你知道怎么把录音转成文字吗&#xff1f;我今天录了一个重要的会议&#xff0c;但是时间有限&#xff0c;需要快速整理笔记。 小辉&#xff1a;当然&#xff01;你可以使用一些工具来将录音转换为文字。最简单的方法就是利用语音转文字的应用。…

C语言 while 和 do while 区别

先简单介绍一下C语言中的while和do while语句 while循环 语法 C 语言中 while 循环的语法&#xff1a; while(condition) {statement(s); } 在这里&#xff0c;statement(s) 可以是一个单独的语句&#xff0c;也可以是几个语句组成的代码块。 condition 可以是任意的表达…

Kubernetes 启动Pod的方法-Pod的调度算法-Pod间的通信-k8s的控制器-Pod资源控制-发布Service服务

目录 Pod 参考文档&#xff1a;Pod | Kubernetes Pod配置文件&#xff1a;simple-pod.yaml 对master进行如下操作 Pod的状态有&#xff1a; 参考文档&#xff1a;(70条消息) Pod生命周期中的状态解释_pod状态_闹玩儿扣眼珠子的博客-CSDN博客 进入Pod内的nginx容器&#…