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], ...
随机推荐
- CentOS 7 分区
必须的分区 boot分区: 作用:引导分区,包含了系统启动的必要内核文件,即使根分区顺坏也能正常引导启动 一般这些文件所占空间在200M以下, 分区建议:分区的时候可选100M-500M之间,如果空间 ...
- Misc题目
@freebuff教程https://www.freebuf.com/column/196815.html @巅峰极客wp https://www.anquanke.com/post/id/18914 ...
- TensorFlow实战第二课(添加神经层)
莫烦tensorflow实战教学 1.添加神经层 #add_layer() import tensorflow as tf def add_layer(inputs,in_size,out_size, ...
- python 实现 灰色预测 GM(1,1)模型 灰色系统 预测 灰色预测公式推导
来源公式推导连接 https://blog.csdn.net/qq_36387683/article/details/88554434 关键词:灰色预测 python 实现 灰色预测 GM(1,1)模 ...
- python 连接Oracle 的步骤
1. 安装 cx_Oracle pip install cx_Oracle 2.配置 oci.dll 与 oraociei11.dll 添加到环境变量path中 下载地址:百度搜索下载,Oracle ...
- NOIp2016 D2T3 愤怒的小鸟【搜索】(网上题解正解是状压)
题目传送门 没啥别的想法,感觉就是搜索,经过原点的抛物线已知两个点就可以求出解析式,在还没有被打下来的两个猪之间随意配对,确定解析式之后标记在这个抛物线下被打下来的猪. 猪也可以单独用一个抛物线打下来 ...
- PTA(Advanced Level)1065.A+B and C
Given three integers A, B and C in [−263,263], you are supposed to tell whether A+B>C. Input Spec ...
- 客户端实现WebService服务接口
首先,要获得搭建好的WebService服务的WSDL,如要实现国内手机号码归属地查询WEB服务,其WSDL为:http://ws.webxml.com.cn/WebServices/MobileCo ...
- 分层最短路(牛客第四场)-- free
题意: 给你边权,起点和终点,有k次机会把某条路变为0,问你最短路是多长. 思路: 分层最短路模板题.题目有点坑(卡掉了SPFA,只能用dijkstra跑的算法). #include<iostr ...
- 2019中山纪念中学夏令营-Day19 数论初步【GCD(最大公约数),素数相关】
关于GCD的一些定理或运用的学习: 1. 2.二进制算法求GCD 思想:使得最后的GCD没有2(提前把2提出来) 代码实现: #include <cstdio> #define int l ...