SPFA -----队列优化的Bellman-Ford
SPFA ------队列优化的Bellman-Ford
由Bellman-Ford算法实现带有负权边的单源最短路,时间复杂度是O(VE),也就是边数乘顶点数。但是根据Bellman-Ford的状态转移方程$$dist[i] = min(dist[i] , last[k] + w[k -> i])$$可知,当且仅当顶点k的dist值在上一层有更新时,在本层更新时顶点 i 的dist值才有可能变小。因此SPFA出现了
SPFA算法相较于Bellman-Ford多维护了一个队列,队列中存储可能使得最短路获得更新的顶点。每次更新我们仅使用队列中的顶点来进行更新,同时每次将更新过的顶点加入队列,这样就避免了无用的更新操作。
SPFA求带负权边的单源最短路
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N = 1e5+20;
int n,m;
vector<pair<int,int>> g[N];
int dist[N];
bool st[N]; //判断该顶点是否已经在队列中,防止重复入队
void spfa()
{
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
queue<int> q;
q.push(1); //将源点加入队列中
st[1] = true;
while(q.size())
{
int k = q.front();
q.pop();
st[k] = false; //出队后状态置为false
for(auto x : g[k])
{
int v = x.first, w = x.second;
if(dist[v] > dist[k] + w)
{
dist[v] = dist[k] + w;
if(!st[v]) //防止重复入队
{
q.push(v);
st[v] = true;
}
}
}
}
}
int main()
{
cin >> n >> m;
while(m --)
{
int x,y,z;
cin >> x >> y >> z;
g[x].push_back({y,z});
}
spfa();
if(dist[n] > 0x3f3f3f3f/2) puts("impossible");
else cout << dist[n];
return 0;
}
SPFA判断图中是否有负环
和Bellman-Ford一样,当图中出现负环时(如下图)
A((A)) -->|2| B((B))
B -->|-5| C((C))
C -->|1| A
根据从源点到目标点的最短路至多经过n-1条边,当存在负环时,更新操作可以一直进行,也就是说边数会大于n-1。我们只需要监视在更新过程中是否出现经过边数大于n-1即可。
如下题
852. spfa判断负环 - AcWing题库
代码如下
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N = 2500;
vector<pair<int,int>> g[N];
int dist[N];
int st[N],cnt[N];
int n,m;
bool spfa()
{
queue<int> q;
for(int i = 1 ; i <= n ; i++)
{
q.push(i);
st[i] = true;
}
while(q.size())
{
int k = q.front();
q.pop();
st[k] = false;
for(auto x : g[k])
{
int v = x.first, w = x.second;
if(dist[v] > dist[k] + w)
{
dist[v] = dist[k] + w;
cnt[v] = cnt[k] + 1;
if(cnt[v] >= n)
return true;
if(!st[v])
{
q.push(v);
st[v] = true;
}
}
}
}
return false;
}
int main()
{
cin >> n >>m;
while(m --)
{
int x,y,z;
cin >> x >> y >> z;
g[x].push_back({y,z});
}
if(spfa())
cout << "Yes";
else
cout << "No";
return 0;
}
几点细节
- 这里开始将所有顶点都入队,是因为若仅使用一个源点的话,出现孤立的不连通块会使得我们在找负环或者说更新最短路时有疏漏。因此初始将所有顶点加入队列,且不用初始化dist数组。因为我们目标是找出负值圈,而如果有负值圈,最短路会小于0且会一直更新,也就是说队列永远不会空,且dist会一直减小。我们只需要在某个节点检测到cnt[v] >= n即可
- 以上将所有顶点入队的操作也可以理解为有一个虚拟的源点s,其与图中各个点都有一条权值为0的点,也就说该虚拟源点使得图联通起来。然后使用该虚拟源点更新就是将各个顶点加入队列。
- 关于cnt[v] = cnt[k] + 1。显然若k顶点能够更新dist[v],那么顶点v的最短路所经过的边数即为顶点k所经过的边数加上更新的这条边数。
SPFA -----队列优化的Bellman-Ford的更多相关文章
- SPFA队列优化
spfa队列优化(用来求最短路) 实现方法: 1.存入图.可以使用链式前向星或者vocter. 2.开一个队列,先将开始的节点放入. 3.每次从队列中取出一个节点X,遍历与X相通的Y节点,查询比对 ...
- 最短路--spfa+队列优化模板
spfa普通版就不写了,优化还是要的昂,spfa是可以判负环,接受负权边和重边的,判断负环只需要另开一个数组记录每个结点的入队次数,当有任意一个结点入队大于点数就表明有负环存在 #include< ...
- poj1860 bellman—ford队列优化 Currency Exchange
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22123 Accepted: 799 ...
- 关于SPFA的双端队列优化
7.11 Update 我做题的时候发现这样写会RE 因为在使用双端队列优化SPFA的时候 在将一个点加入队列的时候,如果队列已经空了 那么一旦出现dis[Q.front()]就会RE 可以这样修改 ...
- HDU 2544 最短路(floyd+bellman-ford+spfa+dijkstra队列优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目大意:找点1到点n的最短路(无向图) 练一下最短路... dijkstra+队列优化: #i ...
- 队列优化dijsktra(SPFA)的玄学优化
转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2 优化 对一些数 ...
- poj 3259 Wormholes : spfa 双端队列优化 判负环 O(k*E)
/** problem: http://poj.org/problem?id=3259 spfa判负环: 当有个点被松弛了n次,则这个点必定为负环中的一个点(n为点的个数) spfa双端队列优化: 维 ...
- Bellman-Ford算法及其队列优化(SPFA)
一.算法概述 Bellman-Ford算法解决的是一般情况下的单源最短路径问题.所谓单源最短路径问题:给定一个图G=(V,E),我们希望找到从给定源结点s属于V到每个结点v属于V的最短路径.单源最短路 ...
- SPFA(Bellman-Ford队列优化)
原理:队列+松弛操作 将源点加入队尾,每一步读取队头顶点u,并将队头顶点u出队(记得消除标记):将与点u相连的所有点v进行松弛操作,如果能更新距离(即令d[v]变小),那么就更新,另外,如果点v没有在 ...
- 图论之最短路径(3)队列优化的Bellman-Ford算法(SPFA算法)
在Bellman-Ford算法中 我们可以看到大量的优化空间:如果一个点的最短路径已经确定了,那么它就不会再改变,因此不需要再处理.换句话说:我们每次只对最短路径改变了的顶点的所有出边进行操作 使用一 ...
随机推荐
- 阿里云 Serverless 异步任务处理系统在数据分析领域的应用
异步任务处理系统中的数据分析 数据处理.机器学习训练.数据统计分析是最为常见的一类离线任务.这类任务往往都是经过了一系列的预处理后,由上游统一发送到任务平台进行批量训练及分析.在处理语言方面,Pyth ...
- vue 状态管理 一、状态管理概念和基本结构
系列导航 vue 状态管理 一.状态管理概念和基本结构 vue 状态管理 二.状态管理的基本使用 vue 状态管理 三.Mutations和Getters用法 vue 状态管理 四.Action用法 ...
- 【驱动】以太网扫盲(三)PHY的控制器驱动框架分析
1. 概述 PHY芯片为OSI的最底层-物理层(Physical Layer),通过MII/GMII/RMII/SGMII/XGMII等多种媒体独立接口(介质无关接口)与数据链路层的MAC芯片相连,并 ...
- 使用 Docker Compose V2 快速搭建日志分析平台 ELK (Elasticsearch、Logstash 和 Kibana)
前言 ELK 是指 Elasticsearch.Logstash 和 Kibana 这三个开源软件的组合. Elasticsearch 是一个分布式的搜索和分析引擎,用于日志的存储,搜索,分析,查询. ...
- @Async异步操作及异步线程池
本文为博主原创,转载请注明出处: @Async 用来实现异步请求操作,使用@Async 注解时,需要同时使用 @EnableAsync 注解,使用 @EnableAsync 注解用于开启异步请求. 如 ...
- 基于python+django的电影搜索网站-搜索引擎系统设计与实现
该项目是基于python的web类库django开发的一套web网站,给师弟做的课程设计. 本人的研究方向是一项关于搜索的研究项目.在该项目中,笔者开发了一个简单版的搜索网站,实现了对数据库数据的检索 ...
- SD Host控制器微架构设计
微架构设计思路 ahb_slave_if中的寄存器可以在datasheet中进行描述 sd_clk - 时钟产生模块的接口描述 sd_data_fsm和sd_cmd_fsm - 状态机描述 发送时序需 ...
- css - 伪元素清除浮动
.clearfix:after{ content:""; /*设置内容为空*/ height:0; /*高度为0*/ line-height:0; /*行高为0*/ display ...
- NodeJS安装指南(Mac)
nvm,node,npm之间的区别 nvm:nodejs 版本管理工具. 也就是说:一个 nvm 可以管理很多 node 版本和 npm 版本. nodejs:在项目开发时的所需要的代码库 npm:n ...
- Android——“EditText控件供获取最大长度的方法”
package utils; import android.app.Activity; import android.content.Context; import android.text.Inpu ...