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算法中 我们可以看到大量的优化空间:如果一个点的最短路径已经确定了,那么它就不会再改变,因此不需要再处理.换句话说:我们每次只对最短路径改变了的顶点的所有出边进行操作 使用一 ...
随机推荐
- 使用 Sealos 将 ChatGLM3 接入 FastGPT,打造完全私有化 AI 客服
FastGPT 是一款专为客服问答场景而定制的开箱即用的 AI 知识库问答系统.该系统具备可视化工作流功能,允许用户灵活地设计复杂的问答流程,几乎能满足各种客服需求. 在国内市场环境下,离线部署对于企 ...
- python常见面试题讲解(十二)句子逆序
题目描述 将一个英文语句以单词为单位逆序排放.例如"I am a boy",逆序排放后为"boy a am I"所有单词之间用一个空格隔开,语句中除了英文字母外 ...
- java进阶(14)--日期时间处理
一.获取系统当前时间: 1.Date(),精确到毫秒的当前当前时间 2.示例,欧美风格时间格式
- Java求一个集合的所有子集
转载请注明出处: 求一个集合的所有子集表示从一个集合当中,任取任意项或不取,所能得到的所有结果,比如有一个集合{a,b,c,d},那么{a,b}, {b, d}等都是它的子集,空集也是它的子集, 一个 ...
- SD Host控制器微架构设计-02
SD_clk 测试模式下,选择hclk,将扫描链中的时钟保持一致 clk_en表示可以通过软硬件关闭时钟 sd_if模块 模块中设置一些寄存器,我们可以对寄存器进行读写或者对于寄存器中的某些域段进行读 ...
- Laravel - 使用ajax
一,前台模板文件 index.blade.php <!DOCTYPE html> <meta name="_token" content="{{ cs ...
- [转帖]必看!PostgreSQL参数优化
https://zhuanlan.zhihu.com/p/333201734 前不久,一个朋友所在的公司,业务人员整天都喊慢. 朋友是搞开发的,不是很懂DB,他说他们应用的其实没什么问题,但是就是每天 ...
- CPU算力提升与实际性能提升的关系
关于SPEC2006CPU和RedisBenchmark的理解 最近研究过硬件CPU的性能和Redis这样单线程重IO服务 突然想对比一下CPU算力提升占Redis性能提升的比率情况 性能很大程度由C ...
- [转帖]vCenter使用 VMCA 续订证书:续订证书时发生意外错误
https://www.dinghui.org/vcenter-sts-certificate.html 起因:有一处客户vCenter告警:STS签名证书即将过期. 处理办法:系统管理-证书-证书管 ...
- [转帖]Elasticsearch-索引性能调优
1:设置合理的索引分片数和副本数 索引分片数建议设置为集群节点的整数倍,初始数据导入时副本数设置为 0,生产环境副本数建议设置为 1(设置 1 个副本,集群任意 1 个节点宕机数据不会丢失:设置更多副 ...