BFS:解决多源最短路问题

news2025/1/13 9:45:54

文章目录

  • 什么是多源最短路问题?
  • 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算法的应用场景及其实现方法,为今后的算法学习和实际应用提供帮助。

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

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

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

相关文章

正则表达式,linux文本三剑客

正则表达式匹配的是文本内容&#xff0c;linux的文本三剑客都是针对文本内容&#xff0c;按行进行匹配 文本三剑客&#xff1a; grep 过滤文本内容 sed 针对文本内容进行增删改查 awd 按行取列 一.grep命令 作用就是使用正则表达式来匹配文本内容 -m 数字&#xff1a;匹配…

VMware与windows的共享文件夹没找到怎么办?

如果这样子添加&#xff0c;在ubuntu中还是没能找到。开机后有的时候仍然未发现共享文件夹。 二、解决办法 使用如下指令&#xff1a; sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other /mnt/hgfs/ 是挂载点&#xff0c;也可以指定其它挂载点 -o allow_other…

第14章. GPIO简介

目录 0. 《STM32单片机自学教程》专栏 14.1 GPIO基本结构 14.1.1 保护二极管 14.1.2 上拉、下拉电阻 14.1.3 施密特触发器 14.1.4 P-MOS 管和 N-MOS 管 14.1.5 输出数据寄存器 14.1.6 输入数据寄存器 14.2 GPIO工作模式 14.2.1 输入模式 14.2.1.1 输入浮空模式 1…

Nginx自定义错误页面配置

Nginx错误页面包括404 403 500 502 503 504等页面&#xff0c;只需要在server中进行如下配置即可&#xff1a; error_page 404 500 502 503 504 /50x.html;location /50x.html {root /usr/share/nginx/html;}注意&#xff1a; /usr/local/nginx/html/ 路径下必须有50x.ht…

Node.js版Selenium WebDriver教程

目录 介绍 导言 Selenium基础 环境设置 使用npm安装selenium-webdriver模块 配置和管理浏览器驱动器 下载火狐 下载安装 webDriver 第一个WebDriver脚本 介绍 导言 在当今数字化时代&#xff0c;Web应用程序的质量和性能至关重要。为了确保这些应用的可靠性&#xf…

国产大模型技术创新分析

国产模型百舸争流&#xff0c;技术创新百花齐放 2023年下半年起&#xff0c;国内大模型领域迎来“百模大战”&#xff0c;各大厂商纷纷加速生成式AI的研发与突破&#xff0c;模型持续迭代升级&#xff0c;展现了人工智能技术的蓬勃发展与无限潜力。 中国大模型市场迅猛发展&am…

SpringBoot-注解@ImportResource引入自定义spring的配置xml文件和配置类

1、注解ImportResource 我们知道Spring的配置文件是可以有很多个的&#xff0c;我们在web.xml中如下配置就可以引入它们&#xff1a; SprongBoot默认已经给我们配置好了Spring&#xff0c;它的内部相当于已经有一个配置文件&#xff0c;那么我们想要添加新的配置文件怎么办&am…

SQL-Python

师从黑马程序员 数据库介绍 数据库就是存储数据的库 数据组织&#xff1a;库->表->数据 数据库和SQL的关系 MySQL的基础命令 SQL基础 SQL语言的分类 SQL的语法特征 DDL-库管理 show DATABASES;use sys;SELECT database();CREATE DATABASE test CHARSET utf-8;SHOW D…

【Orange Pi 5与Linux编程编程】-POSIX消息队列

Linux系统中的POSIX消息队列编程 文章目录 Linux系统中的POSIX消息队列编程1、POSIX 消息队列2、Linux 中的 POSIX 消息队列命名3、POSIX 消息队列调用3.1 mq_open, mq_close3.2 mq_timed_send、mq_send、mq_timed_receive、mq_receive3.3 mq_notify3.4 mq_unlink3.5 mq_getatt…

SpringCloud - 微服务

1、微服务介绍 参考&#xff1a; 微服务百度百科 1.1 概念 微服务&#xff08;或称微服务架构&#xff09;是一种云原生架构方法&#xff0c;在单个应用中包含众多松散耦合且可单独部署的小型组件或服务。 这些服务通常拥有自己的技术栈&#xff0c;包括数据库和数据管理模型&…

可视化大屏开发系列——DataV的使用

以下内容为近期个人学习总结&#xff0c;若有错误之处&#xff0c;欢迎指出&#xff01; 可视化大屏开发系列——DataV的使用 一、介绍二、注意事项1、技术支持2、兼容性3、状态更新 三、实现效果四、使用&#xff08;在vue2项目中&#xff09;1.npm安装2.main.js中引入3.开启愉…

昇思25天学习打卡营第5天|网络构建

一、简介&#xff1a; 神经网络模型是由神经网络层和Tensor操作构成的&#xff0c;mindspore.nn提供了常见神经网络层的实现&#xff0c;在MindSpore中&#xff0c;Cell类是构建所有网络的基类&#xff08;这个类和pytorch中的modul类是一样的作用&#xff09;&#xff0c;也是…

LVGL8.3动画图像(太空人)

LVGL8.3 动画图像 1. 动画图像本质 我们知道电影属于视频&#xff0c;而电影的本质是将一系列动作的静态图像进行快速切换而呈现出动画的形式&#xff0c;也就是说动画本质是一系列照片。所以 lvgl 依照这样的思想而定义了动画图像&#xff0c;所以在 lvgl 中动画图像类似于普…

【学习笔记】Mybatis-Plus(三):MP中Wrapper的使用

Wrapper简介 注意&#xff1a; 查询用QueryWrapper和LambdaQueryWrapper来封装 updateWrapper和LambdaUPdateWrapper不但能封装查询还能更改要更新的对象。 QueryWrapper的使用 QueryWrapper中的很多条件限定都是见名知其意的。下表列出来几个常用的&#xff1a; 1.多条件进行…

【八】【QT开发应用】QTcreate项目打包成.exe文件或.apk文件,EnigmaVirtualBox软件下载,虚拟网站代打开QT应用

EnigmaVirtualBox下载 Enigma Virtual Box QTcreate项目打包成.exe可执行文件 找到自己写好的项目的.exe文件 将这个文件复制到一个新的文件夹里面 在这个新的文件夹里面打开cmd,这样可以使得cmd直接进入到该文件夹 打包.exe命令行 输入下面的命令行 windeployqt game…

EndNote 21 for Mac v21.3 文献管理软件安装

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行安装EndNote212、升级 三、运行1、打开软件&#xff0c;测试 安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件 链接&#xff1a;http://www.macfxb.cn 二、开始安装 1、双击运行安装End…

【目标检测】DAB-DETR

一、引言 论文&#xff1a; DAB-DETR: Dynamic Anchor Boxes are Better Queries for DETR 作者&#xff1a; IDEA 代码&#xff1a; DAB-DETR 注意&#xff1a; 该算法是对DETR的改进&#xff0c;在学习该算法前&#xff0c;建议掌握多头注意力、Sinusoidal位置编码、DETR等相…

一款基于WordPress开发的高颜值的自适应主题Puock

主题特性 支持白天与暗黑模式 全局无刷新加载 支持博客与CMS布局 内置WP优化策略 一键全站变灰 网页压缩成一行 后台防恶意登录 内置出色的SEO功能 评论Ajax加载 文章点赞、打赏 支持Twemoji集成 支持QQ登录 丰富的广告位 丰富的小工具 自动百度链接提交 众多页面模板 支持评论…

富文本编辑器CKEditor

介绍 富文本编辑器不同于文本编辑器,它提供类似于 Microsoft Word 的编辑功能 在Django中,有可以现成的富文本三方模块django-ckeditor,具体安排方式: pip install django-ckeditor==6.5.1官网:Django CKEditor — Django CKEditor 6.7.0 documentation 使用方式 创建项…

torchinfo这个包中的summary真的很好用

1.安装直接使用 pip 进行安装即可&#xff1a; pip install torchinfo 2.导入该模块 from torchinfo import summary 3.使用模块 summary(model)#这里的model是你自己的model&#xff0c;可以添加参数进去 4.效果图&#xff1a; 第一个图片是直接打印model吗&#xff0c;…