经过笔者的多次实践(失败),在此温馨提示:用SPFA判负环时一定要特别小心!

首先SPFA有BFS和DFS两种实现方式,两者的判负环方式也是不同的。

      BFS是用一个num数组,num[x]表示从1到x的最短路径包含的边数,当执行松弛操作d[y]=d[x]+w时,同样更新num[y]=num[x]+1,若此时发现num[y]>=n,则图中有负环(显然,n个点n条不重的边,必定又环)。DFS则是换了一种思路:把d数组的初值置为0,这样就能保证走过的路径和一直为负,排除了大量无关路径。但是这样判断的是是否有经过起始点的负环,因此要判断整个图中是否有负环的话,得把n个点全跑一遍。看起来是简单,但有以下注意事项:

  1. 如果只是判负环,使用DFS比BFS一般要快得多。
  2. DFS判断负环时,dis数组初值应该都设为0。
  3. 不要指望DFS在判断负环的同时还能求最短路了。
  4. 用DFS判断负环,不能只把一个点作为源点跑一次,而要把1-n每个都作为源点跑一遍SPFA,才能保证结果的正确。
  5. 还有一种比较玄学的判负环方式,就是正常地跑BFS的SPFA,如果扩展了MAXN次还没出结果,就判定有负环(MAXN为根据题目规模自拟的常量),原理简单易懂:跑了这么久还没出结果,当然是有负环咯~~NB的是经实测正确率还相当高!当然相当高还是牺牲了算法的正确性的,因此不到万不得已之时不建议使用(玄学你懂的)。

BFS判负环(部分):

 bool SPFA(){
queue<int> q;
for(int i=;i<=n;++i) d[i]=INF;
memset(num,,sizeof num);
while(!q.empty()){
int h=q.front();q.pop();
vis[h]=false;
for(int p=G.tail[h];p;p=G.e[p].last){
int &v=G.e[p].v,&w=G.e[p].w;
if(d[v]>d[h]+w){
d[v]=d[h]+w;
num[v]=num[h]+;
if(num[v]>=n) return true;
if(!vis[v])
q.push(v),vis[v]=true;
}
}
}
return false;
}

BFS判负环的另一种方式是用num[x]记录x入队的次数,如过某个num[x]>=n则判定有负环。但这种方法一般不如上面介绍的快,例如在n个结点构成一个负环的图中(这也是一种常见的卡的图),上面的方法只需绕环一次即可判定负环,而这种方法则需绕环n次。

DFS判负环(部分):

 bool SPFA(int x){
vis[x]=true;
for(int p=G.tail[x];p;p=G.e[p].last){
int &v=G.e[p].v,&w=G.e[p].w; if(d[v]>d[x]+w){
d[v]=d[x]+w;
if(vis[v]){vis[x]=false;return true;}
if(SPFA(v)){vis[x]=false;return true;}
}
}
return vis[x]=false;
}
bool check(){
memset(d,,sizeof d);
for(int i=;i<=n;++i) if(SPFA(i)) return true;
return false;
}

  为什么第7和第8行要写个vis[x]=false?因为我们没有执行第11行,如果不写的话就无法把vis数组置0了,这样我们每次SPFA都得memset(vis,0,sizeof vis),很麻烦。

来一道很模板的例题:https://loj.ac/problem/10086

如此猖狂的出题人怎么可以忍???此题的特点是先判负环,若无负环求单源最短路。一开始我是小看这道题了,想用一次SPFA_DFS解决问题,结果有一个测试点负环没判到,还有一个点T了(说好的不必为超时担心呢=-=)。果然鱼和熊掌不可兼得,修改策略:先用SPFA_DFS判负环,如果没有再用正常的SPFA_BFS求最短路,就可以A了。

     要注意vis数组对于DFS和BFS的SPFA意义是不太一样的,判断负环与求最短路时对dis数组的初始化赋值也不一样。

     本蒟蒻建议:用DFS判负环,用BFS求最小路。

2018-08-18

SPFA算法的判负环问题(BFS与DFS实现)的更多相关文章

  1. spfa算法及判负环详解

    spfa     (Shortest Path Faster Algorithm) 是一种单源最短路径的算法,基于Bellman-Ford算法上由队列优化实现. 什么是Bellman_Ford,百度内 ...

  2. poj3259 Wormholes (判负环)【spfa】(模板)

    <题目链接> 题目大意: John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时间会倒退Ts.我们的任务是知道会不会在从 ...

  3. [poj3259]Wormholes(spfa判负环)

    题意:有向图判负环. 解题关键:spfa算法+hash判负圈. spfa判断负环:若一个点入队次数大于节点数,则存在负环.  两点间如果有最短路,那么每个结点最多经过一次,这条路不超过$n-1$条边. ...

  4. 浅谈SPFA判负环

    目录 SPFA判负环 [前言] [不可代替性] [具体实现] SPFA的过程 判负环 [核心代码] [例题] SPFA判负环 有不足的地方请指出 本蒟蒻一定会修改吼 [前言] 最短路的求法中最广为人知 ...

  5. Poj 3259 Wormholes(spfa判负环)

    Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42366 Accepted: 15560 传送门 Descr ...

  6. BZOJ.4500.矩阵(差分约束 SPFA判负环 / 带权并查集)

    BZOJ 差分约束: 我是谁,差分约束是啥,这是哪 太真实了= = 插个广告:这里有差分约束详解. 记\(r_i\)为第\(i\)行整体加了多少的权值,\(c_i\)为第\(i\)列整体加了多少权值, ...

  7. spfa判负环

    bfs版spfa void spfa(){ queue<int> q; ;i<=n;i++) dis[i]=inf; q.push();dis[]=;vis[]=; while(!q ...

  8. BZOJ 4898 [APIO2017] 商旅 | SPFA判负环 分数规划

    BZOJ 4898 [APIO2017] 商旅 | SPFA判负环 分数规划 更清真的题面链接:https://files.cnblogs.com/files/winmt/merchant%28zh_ ...

  9. [P1768]天路(分数规划+SPFA判负环)

    题目描述 “那是一条神奇的天路诶~,把第一个神犇送上天堂~”,XDM先生唱着这首“亲切”的歌曲,一道猥琐题目的灵感在脑中出现了. 和C_SUNSHINE大神商量后,这道猥琐的题目终于出现在本次试题上了 ...

随机推荐

  1. SpringBoot_02通用mapper

    注意:一旦引入了通用Mapper的启动器,会覆盖Mybatis官方启动器的功能,因此需要移除对官方Mybatis启动器的依赖. 无需任何配置就可以使用了.如果有特殊需要,可以到通用mapper官网查看 ...

  2. P1216数字三角形

    这是USACO的一道记忆化搜索题,还记得原来学搜索就是被此所困. 给定n深的数,第i层有i个节点,存储有一个数字,询问从第一层走到最后一层所经过节点上数字和的最大值.我们很容易想到枚举所有路径来计算最 ...

  3. 初相识|performance_schema全方位介绍

    初相识|performance_schema全方位介绍 |导 语 很久之前,当我还在尝试着系统地学习performance_schema的时候,通过在网上各种搜索资料进行学习,但很遗憾,学习的效果并不 ...

  4. 安装ELK平台 7.3.0版本

    0. 事前准备工作 0.1 防火墙 若是使用公网IP的话可以考虑关闭防火墙,或者放行相应端口 使用内网IP的话可以不用管防火墙 0.2 关闭SElinux # setenforce 0 文件:/etc ...

  5. 11.jQuery之淡入淡出效果

    知识点:fadeIn   fadeOut  fadeToggle  fadeTo <style> div { width: 150px; height: 300px; background ...

  6. mycat 笔记

    Mycat读写分离.主从切换.分库分表的操作记录   系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库 ...

  7. vue项目进行时,script标签中,methods事件中函数使用的async/await

    用 async/await 来处理异步 await关键字只能放到async函数里面,通过await得到就是Promise返回的内容:当然也能通过then()去获取,若通过then()获取了则就无Pro ...

  8. Java RMI 最简单实例

    IHello.java import java.rmi.Remote; import java.rmi.RemoteException; public interface IHello extends ...

  9. 2019-11-29-VisualStudio-解决方案筛选器-slnf-文件

    title author date CreateTime categories VisualStudio 解决方案筛选器 slnf 文件 lindexi 2019-11-29 08:41:13 +08 ...

  10. Source Insight 中调用Notepad++

    options>custom commands 指令为 "E:\Program Files (x86)\Notepad++\notepad++.exe" %f 其中%f表示S ...