spfa算法及判负环详解
spfa (Shortest Path Faster Algorithm)
是一种单源最短路径的算法,基于Bellman-Ford算法上由队列优化实现。
什么是Bellman_Ford,百度内食用QWQ
也就是说,Bellman_Ford是一种无脑,疯狂松弛的算法。其复杂度为O(nm),可想而知,对于上万的数据会炸的一塌糊涂。。。
相对而言,SPFA显得就没那么无脑了。
在Bellman_Ford算法上,我们找到了一种优化松弛的方法:对于其子边没有进行松弛的松弛操作,当前操作不可能得出正确结果,只能需要后期子边全部被松弛为最佳结果后再进行松弛得到当前边的最佳结果。
那么,在理解这个后,我们搞一个队列来优化Bellman_Ford。具体的,对于已经被松弛过的点,我们将其入队去更新其他的点,这样相对于原来用没有被优化更新的点去更新其他点来说更优。在当前点优化完其他点后,将其出队,以后也可以进队,用来优化其他边。如此循环往复直到队列为空(没有可以优化的点了),那么求出来的就是最短路。
代码,来源于单源最短路径弱化版。
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#define spfa zhx_ak_ioi using namespace std; const long long inf=; long long n,m,s;
long long dis[],vis[],head[],num_edge=; struct Edge{
long long next,to,dis;
}edge[]; queue <long long> q; void addedge(long long from,long long to,long long dis)
{
num_edge++;
edge[num_edge].next=head[from];
edge[num_edge].to=to;
edge[num_edge].dis=dis;
head[from]=num_edge;
} void spfa()
{
for(long long i=;i<=n;++i)
{
dis[i]=inf;
vis[i]=;
}
dis[s]=;
vis[s]=;
q.push(s);
while(!q.empty())
{
long long u=q.front();
q.pop();
vis[u]=;
for(long long i=head[u];i;i=edge[i].next)
{
long long zhongdian=edge[i].to;
if(dis[zhongdian]>dis[u]+edge[i].dis)
{
dis[zhongdian]=dis[u]+edge[i].dis;
if(!vis[zhongdian])
{
q.push(zhongdian);
vis[zhongdian]=;
}
}
}
}
} int main()
{
scanf("%lld %lld %lld",&n,&m,&s);
for(long long i=;i<=m;++i)
{
long long u,v,w;
scanf("%lld %lld %lld",&u,&v,&w);
addedge(u,v,w);
}
spfa();
for(long long i=;i<=n;++i)
{
if(i==s) printf("0 ");
else printf("%lld ",dis[i]);
}
return ;
}
判断负环:
spfa和Bellman_Ford算法可以用来判断负环。
负环,就是图上一个边权权值和为负数的环,
BFS广搜判断方法
对于一个不存在负环的图,从起点到任意一个点最短距离经过的点最多只有n个。那么定义一个cnt数组,表示当前点从起点(编号设为1)到点i的最短距离包含点的个数。如果一个cnt的值大于n的话,就可以判断负环了。同样的,对于每一次松弛操作,一旦松弛成功,我们就将下一个点的cnt值+1,对于环,我们每次松弛时直接判断cnt值是不是大于n,如果大于,说明找到了负环,那么我们就可以退出直接输出就行。
但是,在找负环时,广搜的性质决定了它的复杂度上并不适合找负环。原因:负环本质上是一条环形链(可以这么想但不一定严谨。),但是BFS考虑面太广了以至于在判环的操作上会考虑其他的不属于这个环的元素,因此搜完整个环的效率会变慢。那么有什么算法能够在遍历到这条链?的时候能够不分心的一口气走到底呢?DFS。
代码就是在原spfa上加入cnt和判断操作。
DFS深搜判断负环方法
与BFS唯一不同就是把队列换成了栈,取刚更新的点一口气继续更新到底。这样就可以一直在环上跑,几圈下来就可以判断并退出了。。
代码就是把BFS代码上换个数据结构。
你问我为什么这个代码中没有出现有关边的负权的判断?
在这上面
如果是负数的话那个条件就可以无限满足并(转圈圈跑)了。
完结。QWQ
spfa算法及判负环详解的更多相关文章
- SPFA算法的判负环问题(BFS与DFS实现)
经过笔者的多次实践(失败),在此温馨提示:用SPFA判负环时一定要特别小心! 首先SPFA有BFS和DFS两种实现方式,两者的判负环方式也是不同的. BFS是用一个num数组,num[x] ...
- poj3259 Wormholes (判负环)【spfa】(模板)
<题目链接> 题目大意: John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时间会倒退Ts.我们的任务是知道会不会在从 ...
- [poj3259]Wormholes(spfa判负环)
题意:有向图判负环. 解题关键:spfa算法+hash判负圈. spfa判断负环:若一个点入队次数大于节点数,则存在负环. 两点间如果有最短路,那么每个结点最多经过一次,这条路不超过$n-1$条边. ...
- 浅谈SPFA判负环
目录 SPFA判负环 [前言] [不可代替性] [具体实现] SPFA的过程 判负环 [核心代码] [例题] SPFA判负环 有不足的地方请指出 本蒟蒻一定会修改吼 [前言] 最短路的求法中最广为人知 ...
- BZOJ.4500.矩阵(差分约束 SPFA判负环 / 带权并查集)
BZOJ 差分约束: 我是谁,差分约束是啥,这是哪 太真实了= = 插个广告:这里有差分约束详解. 记\(r_i\)为第\(i\)行整体加了多少的权值,\(c_i\)为第\(i\)列整体加了多少权值, ...
- BZOJ 4898 [APIO2017] 商旅 | SPFA判负环 分数规划
BZOJ 4898 [APIO2017] 商旅 | SPFA判负环 分数规划 更清真的题面链接:https://files.cnblogs.com/files/winmt/merchant%28zh_ ...
- [P1768]天路(分数规划+SPFA判负环)
题目描述 “那是一条神奇的天路诶~,把第一个神犇送上天堂~”,XDM先生唱着这首“亲切”的歌曲,一道猥琐题目的灵感在脑中出现了. 和C_SUNSHINE大神商量后,这道猥琐的题目终于出现在本次试题上了 ...
- 【原创】SPFA判负环
[定义与概念] 给定一张有向图,若其中存在一个环的所有权值之和为负数,这个环称为负环. [算法实现] 当然,负环的求解可以暴搜,但是时间复杂度就难以入眼了,我们回到求解单源最短路径算法上面,看看它们能 ...
- poj 3621 二分+spfa判负环
http://poj.org/problem?id=3621 求一个环的{点权和}除以{边权和},使得那个环在所有环中{点权和}除以{边权和}最大. 0/1整数划分问题 令在一个环里,点权为v[i], ...
随机推荐
- laravel多主多从配置示例
'mysql' => [ 'write' => [ [ 'host' => '192.168.1.180', 'username' => '', 'password' => ...
- 前端常用资源地址: http://www.htmleaf.com/
前端常用资源地址: http://www.htmleaf.com/
- JavaScript基础入门04
目录 JavaScript 基础入门04 JavaScript 对象 介绍 关于键名 对象的引用 语句和表达式需要注意的地方 对象属性常见的操作 with语句 JSON 特点 语法规则 JSON合法示 ...
- Spark分区实例(teacher)
package URL1 import org.apache.spark.Partitioner import scala.collection.mutable class MyPartitioner ...
- web题
@php绕过https://www.cnblogs.com/leixiao-/p/9786496.html @step1:F12 step2:抓包 @任何url http://118.25.14.4 ...
- finereport 通过条件弹出 alert进行提示
function convertDateFromString(dateString) { if (dateString) { var date = new Date(dateString.replac ...
- 关于8086中的jmp near ptr原理
在8086汇编语言中.jmp 0x7c41 自己跳转到自己的位置,是一个死循环代码.对应的机器指令是e9fdffe9是跳转 fdff其实应该是fffd 也就是-3的补码. 执行到e9fdff相当于把 ...
- mysql事件(event)
[小结]简单案例 SET GLOBAL event_scheduler=1delimiter $$ create definer = current_user event `test`.`event_ ...
- Storm提交Topology报错:Found multiple defaults.yaml resources.
Storm提交Topology运行方式分为本地和集群运行两种,其中集群运行需要将程序打包并把jar包复制到集群,通过以下方式执行: bin/storm jar /opt/run/storm-demo- ...
- 设计模式在 Spring 框架中的良好应用
在开始正文之前,请你先思考几个问题: 你项目中有使用哪些 GOF 设计模式 说一说 GOF 23 种设计模式的设计理念 说说 Spring 框架中如何实现设计模式 假设我是面试官问起了你这些面试题,你 ...