BFS:解决多源最短路问题

2024-06-23 22:04
文章标签 问题 bfs 解决 短路 多源

本文主要是介绍BFS:解决多源最短路问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 什么是多源最短路问题?
  • 1.矩阵
  • 2.飞地的数量
  • 3.地图的最高点
  • 4.地图分析
  • 总结

在这里插入图片描述

什么是多源最短路问题?

多源最短路问题(Multi-Source Shortest Path Problem,MSSP)是图论中的一个经典问题,它的目标是在给定图中找到从多个源点到所有其他顶点的最短路径。这个问题可以视为单源最短路问题(Single-Source Shortest Path Problem, SSSP)的扩展。
什么是单源最短路问题呢?其实我们上次讲的就可以归结在单元最短路问题当中,其实单源最短路问题就是只有一个起点对应一个终点,求最短路径,而多源最短路问题则是多个起点,对应一个终点,求这多个起点到达终点的最短路径,那这种题我们该怎么做呢?
第一种做法就是将多源最短路问题转换为n个单源最短路问题,循环n次就解决了,但是这种做法是非常慢的。
第二种做法就是把多个节点看成一个整体进行一次单源最短路问题的解法。
这是单源最短路问题问题:
在这里插入图片描述
多源最短路问题:
在这里插入图片描述
我们可以将多源最短路问题的节点看成一个整体,这种方法不仅在计算机领域很常用,在物理数学也很常用,这种方法叫隔离法,我们可以忽略每个节点之间的差异省去了我们比较每个节点差异的过程。

1.矩阵

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题大致的意思就是对一个矩阵做变化,这个矩阵中的数只有两种,一种是1一种是0,我们该如何变换呢?根据题意,变换后节点的值为当前节点的值离最近一个0的节点的距离。按照这个规律首先我们来看看下面的例子,首先零肯定是不会变的,因为零距离最近的零就是他本身,所以这里距离就是0,第二行的1距离最近的零很显然是上左右的零,距离都是1,第三行的1距离醉经的0是上面的0距离为1,但是第三行中间的零距离最近的零是2.
在这里插入图片描述

算法原理:
这里我们已经讲过了做这种题的模式,我们只需要先将所有的零全入到队列中,这些零看成一个整体,在入队列的过程中顺便可以把需要返回的distance数组初始化为-1,然后零的对应位置赋值为0,这里我们直接利用单元最短路向外广搜,也就是整体向外扩散。
在这里插入图片描述
这里红色部分表示我们第一次入进去的0,蓝色部分表示我们第一次扩散,第一次扩散出来的部分应该填1,然后接下来可以继续向外扩散,这里就不展示了。

代码展示:

class Solution {
public:typedef pair<int, int> PII;int dx[4] = { 0,0,1,-1 };int dy[4] = { 1,-1,0,0 };vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {int m = mat.size();int n = mat[0].size();vector<vector<int>> distance(m, vector<int>(n, -1));queue<PII> q;for (int i = 0;i < m;i++){for (int j = 0;j < n;j++){if (mat[i][j] == 0){q.push({ i,j });distance[i][j] = 0;}}}while (q.size()){auto [a, b] = q.front();q.pop();for (int i = 0;i < 4;i++){int x = a + dx[i];int y = b + dy[i];if (x >= 0 && x < m && y >= 0 && y < n&& distance[x][y] == -1){distance[x][y] = distance[a][b] + 1;q.push({ x,y });}}}return distance;}
};

2.飞地的数量

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题的大致意思就是让我们找于边界不联通的1的部分,可以看见第一个例子中的1于外界联通,所以这个1不是最终结果,示例1的三个1周围都是1,1代表海洋,所以这三个1和外界不联通所以这三个1是合法的1,返回这三个1,就是返回3.
算法原理:
在这里插入图片描述
上面这个例子红色代表边界上的与外界相连的1,蓝色代表周围都是0的1,这个例子很显然是返回1的,但是如果我们正面做的话很难,因为我们不知道它是否是与外界相连的,只有把这个岛屿遍历完了才知道是与外界相连的,所以这道题我们正难则反找中间的岛屿不好找,我们直接先把与外界相连的岛屿给标记了,然后对这个二维数组遍历一遍,返回没有被标记过的1的个数。这里具体一点就是对这个二维数组最外面的一层用一次多源BFS,先把所有在外面的1入进队列中,然后并标记,表示这个1已经被访问过了,并且不是内部的岛屿,然后再遍历一遍数组,找到没有被标记的1的个数。
代码展示:

class Solution 
{
public:typedef pair<int,int> PII;bool vis[501][501];int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};int m,n;int numEnclaves(vector<vector<int>>& grid) {queue<PII> q;m=grid.size();n=grid[0].size();for(int i=0;i<m;i++){if(grid[i][0]==1){q.push({i,0});vis[i][0]=true;}if(grid[i][n-1]==1){q.push({i,n-1});vis[i][n-1]=true;}}for(int i=0;i<n;i++){if(grid[0][i]==1){q.push({0,i});vis[0][i]=true;}if(grid[m-1][i]==1){q.push({m-1,i});vis[m-1][i]=true;}}while(q.size()){auto [a,b]=q.front();q.pop();for(int i=0;i<4;i++){int x=a+dx[i];int y=b+dy[i];if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==1&&vis[x][y]==false){q.push({x,y});vis[x][y]=true;}}}int step=0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1&&vis[i][j]==false){step++;}}}return step;}
};

3.地图的最高点

题目链接
题目:

在这里插入图片描述

这道题其实是和第一道题是一样的
样例输出和输入:

在这里插入图片描述

这道题和第一题比较相似。
在这里插入图片描述
我们来看示例2,首先很明显,这道题需要我们返回一个二维矩阵,然后每个元素的特点就是距离最近的一个1的距离,很显然给出的示例中,1里1最近当然就返回的是0,第一个0距离最近的也是1,所以我们只需要照搬第一个题的算法即可,可以说和第一个题一模一样。

代码展示:

class Solution 
{
public:typedef pair<int,int> PII;int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};int m,n;vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {m=isWater.size();n=isWater[0].size();vector<vector<int>> answer(m,vector<int>(n,-1));queue<PII> q;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(isWater[i][j]==1){answer[i][j]=0;q.push({i,j});}}}while(q.size()){auto [a,b]=q.front();q.pop();for(int i=0;i<4;i++){int x=a+dx[i];int y=b+dy[i];if(x>=0&&x<m&&y>=0&&y<n&&answer[x][y]==-1){q.push({x,y});answer[x][y]=answer[a][b]+1;}}}return answer;}
};

4.地图分析

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题其实也是和第一道题一样的但是这道题要求变化后的二维数组中最大的那个数,并返回。

代码展示:

class Solution {
public:typedef pair<int,int> PII;int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};int m,n;int maxDistance(vector<vector<int>>& grid) {m=grid.size();n=grid[0].size();vector<vector<int>> dist(m,vector<int>(n,-1));queue<PII> q;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){q.push({i,j});dist[i][j]=0;}}}int Max=-1;while(q.size()){auto [a,b]=q.front();q.pop();for(int i=0;i<4;i++){int x=a+dx[i];int y=b+dy[i];if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==0&&dist[x][y]==-1){q.push({x,y});dist[x][y]=dist[a][b]+1;Max=dist[x][y];    }}}return Max;}
};

总结

通过本文对BFS算法在解决多源最短路问题中的应用介绍,可以看出BFS在处理无权图的最短路径问题时具有显著优势。它不仅操作简单、直观易懂,而且其广度优先的特点使得它在寻找最短路径时非常高效。多源最短路问题在实际生活中有着广泛的应用,例如交通网络中的最短路径计算、社交网络中的影响力传播等。

在实现过程中,我们需要注意以下几点:

初始化多源节点:确保所有源节点都被正确加入队列,并且其初始距离设置为0。
处理并行搜索:合理安排队列的扩展,保证所有节点都能被正确访问。
避免重复访问:使用访问标记或距离数组来避免节点被重复处理,提高算法效率。
通过实际案例,我们可以看到BFS在解决多源最短路问题时的高效性和可靠性。希望通过这篇文章,读者能够更好地理解BFS算法的应用场景及其实现方法,为今后的算法学习和实际应用提供帮助。

如有任何疑问或建议,欢迎在评论区留言讨论。

这篇关于BFS:解决多源最短路问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1088399

相关文章

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基