【基础算法总结】BFS_多源最短路问题

目录

  • 1. 算法介绍
  • 2. 算法原理和代码实现
    • 542.01矩阵
    • 1020.飞地的数量
    • 1765.地图中的最高点
    • 1162.地图分析
  • 3. 算法总结

1. 算法介绍

所谓多源,就是有多个起点对应上一篇文章【BFS_最短路问题】的单源问题。这篇文章介绍用bfs解决边权为1(或边权相等)的多源最短路问题

我们解决单源问题时,是先把起点入队列,再一层一层向外扩展而多源问题是把所有源点当成一个"超级源点",把"超级源点"加入到队列,再一层一层向外扩展,就变成单源问题了
在这里插入图片描述

如何把所有源点当成"超级源点"?
通过介绍下面的四道题目将给出答案。

2. 算法原理和代码实现

542.01矩阵

在这里插入图片描述
在这里插入图片描述

算法原理:

解法一:暴力求解。每个位置都用一次bfs计算出到最近0的距离,这毫无疑问会超时

解法二:多源bfs+正难则反
把所有的0当成起点,1当成终点。先把所有的0位置加入到队列中,再一层一层扩展即可同时要创建一个与原矩阵等规模的dist矩阵,用来记录距离
在这里插入图片描述

细节/技巧问题:

我们可以回想一下在解决单源最短路问题时,我们定义了一个bool类型的数组vis用来标记该位置是否被遍历过,最少步数step表示扩展层数,每次出队列的个数sz

但是在这个问题中,我们创建的dist矩阵完全可以代替这三个东西,首先把dist矩阵初始化为-1,当dist矩阵的某一位置等于-1,说明原矩阵mat的对应位置没有标记过,当dist的某一位置不为-1,此时该位置记录的就是最近距离,并且原矩阵mat的对应位置标记过

对于step和sz变量的作用,dist也可以代替。因为我们是从坐标[a, b] – > [x,y]进行搜索的,而dist[a,b]记录的等同于就是对应的层数

代码实现:

class Solution 
{int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};
public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {int m = mat.size(), n = mat[0].size();// dist[i][j] == -1:mat[i][j]位置没有标记过// dist[i][j] != -1:最短路vector<vector<int>> dist(m, vector<int>(n, -1));queue<pair<int, int>> q;// 把0源点入队列for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)if(mat[i][j] == 0){q.push({i, j});dist[i][j] = 0;}while(q.size()){auto[a, b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1){q.push({x, y});dist[x][y] = dist[a][b] + 1;}}}return dist;}
};

当然,也可以使用"土方法"解决,这里也给出代码

class Solution
{int m, n;int dx[4] = { 0,0,1,-1 };int dy[4] = { 1,-1,0,0 };
public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat){m = mat.size(), n = mat[0].size();vector<vector<int>> dist(m, vector<int>(n)); // 距离矩阵vector<vector<bool>> vis(m, vector<bool>(n)); // 标记矩阵queue<pair<int, int>> q;// 把所有的0入队列for (int i = 0; i < m; i++){for (int j = 0; j < n; j++){if (mat[i][j] == 0){q.push({ i, j });vis[i][j] = true;}}}int step = 0;while (q.size()){step++;int sz = q.size();while (sz--){auto [a, b] = q.front();q.pop();for (int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y]){dist[x][y] = step;q.push({ x, y });vis[x][y] = true;}}}}return dist;}
};

1020.飞地的数量

在这里插入图片描述
在这里插入图片描述

算法原理:

这道题目可以抽象成多源bfs问题。不直接统计有多少被包围的陆地正难则反,我们从边界上的陆地(1)做突破口把所有边界上的1都入队列,再使用多源bfs进行搜索标记,最后再遍历一遍原数组,统计出没有标记的陆地数量即可
在这里插入图片描述

细节/技巧问题:

参考前文

代码实现:

class Solution 
{bool vis[501][501];int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};
public:int numEnclaves(vector<vector<int>>& grid) {queue<pair<int, int>> q;// 把所有边界上的1入队列int 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 j = 0; j < n; j++){if(grid[0][j] == 1) q.push({0, j}), vis[0][j] = true;if(grid[m-1][j] == 1) q.push({m-1, j}), vis[m-1][j] = true;}// 用多源bfs进行搜索标记while(q.size()){auto[a,b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a+dx[k], y = b+dy[k];if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y]){q.push({x, y});vis[x][y] = 2;}}}// 最后遍历原矩阵,根据标记数组,统计陆地数量int ret = 0;for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)if(grid[i][j] == 1 && !vis[i][j])ret++;return ret;}
};

1765.地图中的最高点

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

算法原理:

这道题完完全全就是第一题的变式题。本题只能根据水域高度推陆地高度,所以可以使用多源bfs把所有水域位置当成"超级源点"入队列,再一层一层向外扩展。代码的实现也几乎一模一样

细节/技巧问题:

参考第一题

代码实现:

class Solution 
{int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};
public:vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {int m = isWater.size(), n = isWater[0].size();vector<vector<bool>> vis(m, vector<bool>(n)); // 标记矩阵vector<vector<int>> hight(m, vector<int>(n)); // 高度矩阵queue<pair<int, int>> q;// 把所有水域入队列,搞定置为0for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)if(isWater[i][j] == 1){q.push({i, j});vis[i][j] = true;hight[i][j] = 0; // 水域的高度为0}// 使用多源bfs进行标记统计while(q.size()){auto[a, b] = q.front();q.pop();for(int k = 0; k < 4 ; k++){int x = a+dx[k], y = b+dy[k];if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y]){hight[x][y] = hight[a][b] + 1;q.push({x, y});vis[x][y] = true;}}}return hight;}
};

1162.地图分析

在这里插入图片描述

在这里插入图片描述

算法原理:

这道题也是第一题的变式题。我们把所有的陆地看成起点入队列,再使用多源bfs向外一层一层扩展
在这里插入图片描述

细节/技巧问题:

参考第一题

代码实现:

class Solution 
{int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};
public:int maxDistance(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();vector<vector<int>> dist(m, vector<int>(n, -1));queue<pair<int, int>> q;for(int i = 0; i < m; i++)for(int j= 0; j < n; j++)if(grid[i][j] == 1){// 所以陆地入队列,距离是0q.push({i, j});dist[i][j] = 0;}int ret = -1;while(q.size()){auto[a, b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a+dx[k], y = b+dy[k];if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1){q.push({x, y});dist[x][y] = dist[a][b] + 1;ret = max(ret, dist[x][y]); // 更新出最大结果}}}return ret;// 下面是另一种更新出最大值的方式//int ret = 0;//int sum = 0;//for(int i = 0; i < m; i++)//    for(int j = 0; j < n; j++)//    {//        sum += dist[i][j];//        if(dist[i][j] >= ret)//            ret = dist[i][j];//    }//return (sum == 0 || sum == -m*n) ? -1 : ret;}
};

3. 算法总结

其实本篇文章的多源最短路和上一篇文章的单源最短路的思想基本上是一模一样的。无非一个是单起点一个是多起点,单起点就把那一个起点入队列就好了,而多起点就看成一个"超级源点"同时入队列就好了。如何把多个起点看成一个"超级源点"是关键,这就要根据题目具体分析了

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

监控平台之rollup打包

设计思路 1.根据模块&#xff0c;通过index.js去调用执行调用 2.WebEyeSDK.js暴露方法&#xff0c;同时定义init方法&#xff0c;去初始化config里的上报参数 3.rollup/build里入口文件为WebEyeSDK.js进行打包 4.打包编译用babel&#xff0c;同时安装babel/preset-env智能预…

网络安全服务基础Windows--第12节-域与活动目录

工作组 在Windows环境中配置⼯作组相对简单&#xff0c;适合⼩型⽹络环境&#xff0c;如家庭或⼩型办公室⽹络。⼯作组通过简单的⽹络共享和本地管理来实现资源共享&#xff0c;⽽不依赖于中央控制的服务器。 ● 定义&#xff1a;⼯作组是⼀种对等⽹络模型&#xff0c;在这种…

【鸿蒙开发从0到1 day05】

一. 清除浮动 1.当外面的大盒子,仅仅只设置了宽度,里面的子盒子为了行排序, 设置了浮动,以至于小盒子脱标,大盒子的高度为0,这个时候就会导致大盒子下面的盒子会跑上去 解决办法方法一:给父盒子添加overflow:hidden,这个就是如果子盒子有溢出,,溢出部分会隐藏方法二:在子盒子的…

Linux【2】文件目录-ls进阶

目录 ls 组合使用&#xff1a;ls -lha​编辑 ls 通配符 ls .是隐藏文件 ls -a可以显示所有文件包括隐藏文件 ls- l列表形式&#xff0c;详细信息 ls -l -h 大小更详细 组合使用&#xff1a;ls -lha ls 通配符 *任意长度 &#xff1f;一个字符 带扩展名 可选from…

计算机网络-VRRP切换与回切过程

前面我们学习了VRRP选举机制&#xff0c;根据VRRP优先级与IP地址确定主设备与备份设备&#xff0c;这里继续进行主备切换与主备回切以及VRRP抢占模式的学习。 一、VRRP主备切换 主备选举时根据优先级选择主设备&#xff0c;状态切换为Master状态&#xff0c;那当什么时候会切换…

HTTPS 协议“加密和解密”详细介绍

目录 一、加密 二、HTTPS的工作过程 2.1 引入对称加密 2.2 引入非对称加密 2.3 中间人攻击 2.4 引入证书 2.5 理解数据签名 2.6 通过证书解决中间人攻击 三、总结 HTTPS 是一个应用层协议&#xff0c;是在 HTTP 协议的基础上引入了一个加密层。 一、加密 加密就是把明文&#x…

Golang环境安装、配置详细

Windows下安装Go开发环境 点我下载 Windows配置Go环境变量 出现工具install失败时&#xff0c;切换其它代理 # 1. 七牛 CDN go env -w GOPROXYhttps://goproxy.cn,direct# 2. 阿里云 go env -w GOPROXYhttps://mirrors.aliyun.com/goproxy/,direct# 3. 官方 go env -w GOP…

【wsl2】从C盘迁移到G盘

参考大神 C盘的ubuntu22.04 非常大&#xff0c;高达30g 迁移后就只有几百M了&#xff1a; 右键有一个move没有敢尝试 迁移过程 Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved.Install the latest PowerShell for new features and improveme…

Xcode插件开发

Xcode插件开发 文章目录 Xcode插件开发一、插件开发流程创建插件Extension文件介绍文件说明 二、插件使用安装说明 一、插件开发流程 创建插件的过程并不复杂&#xff0c;只是官方教程&#xff0c;过于简单&#xff0c;所以这里补充下创建细节 创建插件 环境&#xff1a;Xco…

vue在生产环境和测试环境去掉 console 打印日志 只保留 “error“、 “warn“

vue在生产环境和测试环境去掉 console 打印日志 只保留 “error”、 “warn” 文章目录 vue在生产环境和测试环境去掉 console 打印日志 只保留 "error"、 "warn"一、安装插件二、babel.config.js配置 一、安装插件 npm install babel-plugin-transform-r…

C++11中的function和bind

目录 1.一个引例 2.function 什么是function&#xff1f; function模板原型 function的使用 使用示例代码 使用function解决引例中的问题 3.bind 什么是bind&#xff1f; 如何理解bind&#xff1f; bind的使用 4.function和bind总结 1.一个引例 看下面这一段代码…

仿华为车机UI--图标从Workspace拖动到Hotseat同时保留图标在原来位置

基于Android13 Launcher3,原生系统如果把图标从Workspace拖动到Hotseat里则Workspace就没有了&#xff0c;需求是执行拖拽动作后&#xff0c;图标同时保留在原位置。 实现效果如下&#xff1a; 实现思路&#xff1a; 1.如果在workspace中拖动&#xff0c;则保留原来“改变图标…

前端脚手架,自动创建远程仓库并推送

包含命令行选择和输入配置&#xff0c;远程仓库拉取模板&#xff0c;根据配置将代码注入模板框架的代码中&#xff0c;自动创建远程仓库&#xff0c;初始化git并提交至远程仓库&#xff0c;方便项目开发&#xff0c;简化流程。 目录结构 创建一个bin文件夹&#xff0c;添加ind…

云计算之存储

目录 一、产品介绍 1.1 对象存储oss 1.2 特点 二、产品技术背景 三、产品架构及功能 四、常见问题及排查思路 4.1 两个bucket目录文件如何快速复制&#xff1f; 4.2 oss里的目录如何删除&#xff1f; 4.3 能否统计oss一个目录的大小 4.4 异常诊断 - 上传下载速度慢 4…

CentOS 7安装Docker详细步骤-无坑-丝滑-顺畅

一&#xff0c;安装软件包 yum install -y yum-utils device-mapper-persistent-data lvm2二&#xff0c;更换yum源为阿里源&#xff1a; yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 三&#xff0c;查看docker版本&…

uniapp 自定义微信小程序 tabBar 导航栏

背景 做了一个校园招聘类小程序&#xff0c;使用 uniapp vue3 uview-plus pinia 构建&#xff0c;这个小程序要实现多角色登录&#xff0c;根据权限动态切换 tab 栏文字、图标。 使用pages.json中配置tabBar无法根据角色动态配置 tabBar&#xff0c;因此自定义tabBar&…

交换机自动化备份配置(H3C_无人值守)

介绍&#xff1a; 在日常运维过程中&#xff0c;需要定时备份设备的配置&#xff0c;在设备数量过于庞大的情况下&#xff0c;对我们的运维工作会造成极大地不便&#xff0c;通过python自动化能够完美解决人工手动保存设备配置的问题。而且自动化运维在未来也一定是大势所趋&a…

Spring框架——springweb(一篇包会)

目录 一、Springweb概述 1.SpringWeb特点 2.SpringWeb组件 3.SpringWeb运行流程 二、搭建Springweb 1.导入框架所需的包 2.配置 DispatcherServlet 3.开启SpringWeb注解 4.处理器类搭建 5.请求处理 &#xff08;1&#xff09;接收请求RequestMapping &#xff08;2&…

2.1概率统计的世界

欢迎来到概率统计的世界&#xff01;在量化交易中&#xff0c;概率统计是至关重要的工具。通过理解概率&#xff0c;我们可以用数学的方法来描述市场行为&#xff0c;预测未来走势&#xff0c;并制定交易策略。让我们一起从基础概念开始&#xff0c;逐步深入&#xff0c;揭开概…

vmware中克隆过来的linux节点无system eth0

问题现象 使用vmware虚拟机的克隆功能后&#xff0c;找不到system eth0 解决办法 编辑/etc/udev/rules.d/70-persistent-net.rules文件 可以看到&#xff0c;eth0&#xff0c;是克隆前机器的网卡&#xff0c;eth1是克隆后机器生成的网卡&#xff0c;所以把NAME"eth0&q…