1. 负环的定义:有向图或者是无向图中存在边权之和小于0的环路,对于负环要特殊处理因为在求解最短路的时候如果不处理那么每一次最短距离都会变小就会陷入死循环中,求解负环主要是基于SPFA算法,有两大类方法:
- 统计每一个点入队的次数,若某个点入队n次则说明存在负环
- 统计当前每个点的最短路中所包含的边数,如果某个点的最短路所包含的边数大于等于n,则说明也是存在负环
在找负环的时候一般推荐使用第二种方式,因为第一种方式在极端情况下为一个圈,需要转n - 1圈再加1次某个点才入队n次,所以时间复杂度为O(n ^ 2),而对于第二种做法只转一圈就可以找到负环。在使用spfa找负环的时候需要注意两个问题:① 将所有的点入队;② 所有点的距离值可以初始化为任意值,负环都是可以找出来的,对于①我们其实可以是可以看成是一个虚拟源点,每一个虚拟源点向其余点连一条权重为0的边,原图中存在负环等价于从虚拟源点出发找到负环,并且进一步可以发现在做spfa的时候其实从虚拟源点向每一个点连一条边之后最终会将所有点加入到队列中,所以我们在一开始的时候可以直接将所有点加入到队列中,等价于建立一个虚拟源点;对于②来说因为存在负环所以最终某种的点都会被更新成负无穷,也即需要更新超过n次,因为存在负环的情况下最终最短路径长度一定会大于等于n,所以一开始的时候所有点的距离值初始化为多少都是无所谓的,负环都是可以找出来的。
2. 使用spfa求解负环的时间复杂度接近于O(nm),所以在有的情况下会超时,如果我们发现spfa运行超时了,那么可以提前结束算法认为图中是存在负环的,从经验上看所有点的入队次数超过2n的时候我们就认为图中存在负环,但是在有的情况下是不正确的。