BFS、SPFA、Dijkstra算法中vis数组的用法对比

先上代码:

BFS:

bool vis[MAXN];
int dis[MAXN];void bfs(int s)
{queue<int> Q;Q.push(s);vis[s] = true;while(!Q.empty()){int u = Q.front();Q.pop();for(int e = first[u]; e; e = nxt[e]){int v = go[e];if(vis[v]) continue;dis[v] = dis[u] + 1;vis[v] = true;Q.push(v);}}
}

SPFA:

int dis[MAXN];
bool vis[MAXN];void SPFA(int s)
{for(int i = 1; i <= n; ++i) dis[i] = inf;dis[s] = 0;queue<int> Q;Q.push(s);vis[s] = true;while(!Q.empty()){int u = Q.front();Q.pop();vis[u] = false;for(int e = first[u]; e; e = nxt[e]){int v = go[e];if(dis[v] > dis[u] + val[e]){dis[v] = dis[u] + val[e];if(!vis[v]){Q.push(v);vis[v] = true;}}}}
}

Dijkstra:

struct node
{int u, ds;friend bool operator<(const node& n1, const node& n2){return n1.ds > n2.ds;}
};bool vis[MAXN];
int dis[MAXN];void Dijkstra(int s)
{memset(dis, 0x3f, sizeof(dis));dis[s] = 0;priority_queue<node> Q;Q.push({s, 0});while(!Q.empty()){int u = Q.top().u;Q.pop();if(vis[u]) continue;vis[u] = true;for(int e = first[u]; e; e = nxt[e]){int v = go[e];if(dis[v] > dis[u] + val[e]){dis[v] = dis[u] + val[e];if(!vis[v]) Q.push({v, dis[v]});}}}
}

分析对比

在BFS算法中

当Q.push()调用时顺便设置vis数组。原因是,BFS只能应用于边权为1的有向无环图(Directed Acyclic Graph, DAG),节点v第一次被搜索到时的dis值就是s→v的最短路。因此,在后面又访问到v时,根本不需要干任何事情,既不需要加入队列,也不需要更新dis值。因此,vis数组确保每个点只入队一次、dis值只被更新一次。

在SPFA(队列优化的Bellman-Ford算法)中

vis数组标记了节点v是否在Q中。元素出队时vis设置为false,入队时设置为true。如果节点v已经在队列中,则不需要再次入队。SPFA可以看作时BFS的衍生算法,它可以用于任意图,包括多重图、含有自环的图。对于已经访问过的节点,如果形成环路,后面的节点可以更新前面节点的dis值。其实可以去掉vis数组,但是这样会导致某一时刻队列中包含多个同一元素,极大地降低了算法的效率。因为同一时刻队列中有多个同一元素和只有一个该元素的效果是一样的。

Dijkstra算法是一个较为复杂的算法。根据《算法导论》

Dijkstra算法在运行过程中维持的关键信息是一组结点集合S。从源结点s到该集合中每个结点之间的最短路径已经被找到。算法重复从结点集V-S中选择最短路径估计最小的结点u,将u加入到集合S,然后对所有从u出发的边进行松弛。(P383)
算法维持的不变式为Q=V-S。(P384)(注:V是所有结点的集合,Q是优先队列,S为已经求出最短路的结点集合)
Dijkstra的暴力算法会维持该循环不变式。但我们的算法并不会,因为只有被松驰过的结点才有可能加入队列。理由是,没有被松驰过的结点其dis值一定是inf。Dijkstra还满足一个定理
定理 队列Q中dis值最小的结点u,其dis值就是s→u的最短路。
因此,我们的vis数组的意义是标志结点u是否属于集合S,即结点u的最短路是否已经被计算出来。当u出队时,根据定理,其最短路一定已经被计算出来了,因此标记vis[u]=true。在这之前,我们写道:
if(vis[u]) continue;
不加这句话会TLE。原因何在?为什么同一个结点会出队两次?因为它可能入队两次。或者说,它出队之前被连续松弛了超过一次,导致它在队里有好几个。因此我们使用vis数组,保证不走冤枉路。(亲测,if(!vis[v]) Q.push({v, dis[v]})中if(!vis[v])可以去掉)
区别Dijkstra和SPFA的一个方法是:Dijkstra末有4个右花括号,SPFA有5个

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

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

相关文章

防抖节流的应用场景

1.防抖&#xff1a; 表单验证&#xff1a;当用户在输入框中输入内容时&#xff0c;可以使用防抖来延迟验证用户输入的内容&#xff0c;减少验证的频率。按钮点击&#xff1a;当用户频繁点击按钮时&#xff0c;可以使用防抖来确保只有最后一次点击生效&#xff0c;避免重复提交…

python flask-富文本编辑器的嵌入

富文本编辑器是用来提交大段文字的有效途径&#xff0c;同时也比较美观一些。下面记录下最简用法。首先是pip pip install flask-ckeditor 安装完毕后&#xff0c;观察下面语句&#xff0c;先引入模块然后绑到app上最后就可以个调用了&#xff0c;最简单的取数据方法是&#xf…

外汇天眼:交易如何突破“知行合一”这关?

接触交易之后有无数次想要放弃交易&#xff0c;在交易中的失败实在是太痛苦了&#xff0c;有时候这种失败是打击的作为一个人的最根本的自信&#xff0c;这种失败让我质疑我自己“本就是个普通人&#xff0c;不要想太美的事情”“为什么学习这么多还是不能盈利&#xff0c;我真…

<六>Python的字符串切片及常见操作

字符串的表示 在Python里&#xff0c;可以使用一对单引号、一对双引号或者一对三个双引号、一对三个单引号表示字符串。 a "Im Tom" # 一对双引号 b Tom said:"I am Tom" # 一对单引号c Tom said:"I\m Tom" # 转义字符d Tom said:"…

行业模型与场景落地新样本,网易有道发布多款“子曰”教育大模型落地应用与产品

距离2023年7月正式发布教育大模型“子曰”不到半年时间&#xff0c;教育科技公司网易有道近日再次分享了“子曰”教育大模型创新和落地成果&#xff0c;宣布推出国内首个教育大模型“子曰”2.0版本&#xff0c;同时还发布了基于大模型研发的三大创新应用——AI家庭教师“小P老师…

11.19 校招 实习 内推 面经

绿*泡*泡&#xff1a; neituijunsir 交流裙 &#xff0c;内推/实习/校招汇总表格 1、自动驾驶一周资讯 - 理想汽车发布第三季度财报&#xff1b;小米汽车现身工信部公告&#xff1b;小鹏汽车Q3营收超85亿元&#xff1b;11月前两周新势力销量排行榜 自动驾驶一周资讯 - 理想…

第01章_C语言入门

第01章_C语言入门 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 适合对象 考研同学&#xff0c;且考试科目中包含数据结构等&#xff08;需要使用C/C写代码&#xff09;考研同学&#xff0c;考…

前端如何获取响应头Content-Disposition中的filename,获取文件类型fileType进行不同类型的文件预览

// 预览文件preview: function(item) {var vm = this;if (!item.raw) {var itemBasicId = this.form.itemBasicIdvar url =ctx + /aea/item/basic/getItemDocOrTemplateFile.do?itemBasicId=+itemBasicId+&fileType=applyTableTemplateaxios({method: GET,headers: {Autho…

简述C语言中为什么要用指针

在C语言中&#xff0c;指针的使用是非常重要的&#xff0c;主要由于以下几个原因&#xff1a; 直接访问内存&#xff1a;指针允许程序直接访问和操作内存。这使得程序能够与硬件直接交互&#xff0c;提供了对底层数据结构的更精细控制&#xff0c;这在系统编程中尤其重要。 提…

ChatGPT怎么帮我上班的

1.解放生产力 1&#xff09;标准格式&#xff0c;完美输出。GPT对于公文等具有一定标准格式的文件&#xff0c;可以进行完美仿写&#xff0c;随随便便以假乱真那都是小菜一碟&#xff0c;这对于经常要开展规范成文的人来说&#xff0c;简直就是个福音&#xff0c;只要前期调教…

ruoyi-ai 基于ruoyi-plus实现AI聊天和绘画功能-后端

基于ruoyi-plus实现AI聊天和绘画功能-后端 本项目完全开源免费&#xff01; 后台管理界面使用elementUI服务端使用Java17SpringBoot3.X ruoyi-ai: 基于ruoyi-plus实现AI聊天和绘画功能-后端 实现功能 集成OpenAi API (gpt-4-vision-preview dall-e-3)接入文生图模型&#xf…

如何快速定位php程序运行慢的地方

1 slow log日志 查看slowlog日志位置 编辑php-fpm.conf文件&#xff0c;更改或增加两行内容 slowlog /data/logs/php-slow.log request_slowlog_timeout 2 说明&#xff1a;slowlog定义日志路径和名字&#xff0c;request_slowlog_timeout定义超时时间&#xff0c;单位…

初探Linux环境配置与pyTorch学习

初探Linux环境配置与pyTorch学习 文章目录 初探Linux环境配置与pyTorch学习初探LinuxInstall vmware and ubuntuSwap sourses and typewritingLearn basic command Learn gitLearn .gitignore and git lfsgitignore忽略规则优先级忽略规则匹配语法实例不生效情况 git lfslfs作用…

【每日面试题】精选java面试题之redis

Redis是什么&#xff1f;为什么要使用Redis&#xff1f; Redis是一个开源的高性能键值对存储数据库。它提供了多种数据结构&#xff0c;包括字符串、列表、集合、有序集合、哈希表等。Redis具有快速、可扩展、持久化、支持多种数据结构等特点&#xff0c;适用于缓存、消息队列…

Java/JDK下载安装与环境配置详解

本文将详细介绍如何下载、安装Java开发工具包&#xff08;JDK&#xff09;以及进行环境配置&#xff0c;以便在计算机上顺利运行Java程序。内容包括JDK的下载、安装、环境变量配置、验证安装与配置等。 一、Java简介 Java是一种广泛使用的计算机编程语言&#xff0c;具有跨平…

uni-app 中使用定时器和取消定时器

uni-app 中使用定时器和清除定时器 uni-app 中我们应该如何使用定时器呢&#xff1f;在结束后我们该如何让清除定时器&#xff1f; 下面我们就来分享一下吧。 1、 定义一个 data(){return{timer: null} } 2、设置定时器 //选择适合需求的定时器 this.timer setTimeout( ()…

Django 7 实现Web便签

一、效果图 二、会用到的知识 目录结构与URL路由注册request与response对象模板基础与模板继承ORM查询后台管理 三、实现步骤 1. terminal 输入 django-admin startapp the_10回车 2. 注册&#xff0c; 在 tutorial子文件夹settings.py INSTALLED_APPS 中括号添加 "the…

ffmpeg 5.0版本调试 ffmpeg 5.01 static版本

ffmpeg 5.0版本调试 写法&#xff1a;ffmpeg -rtsp_transport tcp -re -i rtsp://admin:BYTtest2019192.168.1.2:554/h264/ch1/main/av_stream -q 5 -f mpegts -fflags nobuffer -c:v mpeg1video -an -s 960x540 http://127.0.0.1:12345/demo本地写法 ffmpeg -timeout 5000000…

JRTClient打开谷歌

网站默认已经启动https访问&#xff0c;这时候JRTClient发布wss需要浏览器信任证书才能访问打印。为此在JRTClient内部发布了HTTPS服务&#xff0c;有时候浏览器信任的证书会丢失或者被清理掉&#xff0c;这时候需要手工信任下&#xff0c;当然用JRTBrowser就不用信任证书&…

数据库设计——DQL

D Q L \huge{DQL} DQL ⭐⭐⭐⭐⭐ DQL&#xff1a;数据库查询语言&#xff0c;用来查询数据库中的记录&#xff0c;非常的重要&#xff0c;对于数据库的操作修改相对来讲还是较少部分&#xff0c;绝大多数操作都是数据查询。 整体的语法结构&#xff1a; 基本查询 示例&#…