求负环的常用方法,基于SPFA
方法 1:统计每个点入队的次数,如果某个点入队n次,则说明存在负环
方法 2:统计当前每个点的最短路中所包含的边数,如果某点的最短路所包含的边数大于等于n,则也说明存在环
在SPFA的基础上 加一个cnt数组来记录当前 x 点到 虚拟源点 最短路的边数,初始每个点到虚拟源点的距离为0,只要他能再走n步,即 cnt[x] >= n ,则表示该图中一定存在负环,由于从虚拟源点到x至少经过n条边时,则说明图中至少有n + 1个点,表示一定有点是重复使用
C++代码 注释在上一篇spfa文章 spfa求最短路
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N = 1e5+10;
const int M = 1e5+10;
const int inf = 0x3f3f3f3f;
int n,m,idx;
int w[N],to[N],vis[N],nex[N],dis[N],now[N],cnt[N];
void add(int x,int y ,int z){
to[idx] = y;
w[idx] = z;
nex[idx] = now[x];
now[x] = idx++;
}
int spfa(){
queue<int>q;
for(int i = 1; i<=n;i++){
q.push(i);
vis[i]=1;
}
while(q.size()){
int f = q.front();
q.pop();
vis[f] = 0;
for(int i = now[f];i != -1;i = nex[i]){
int j = to[i];
if(dis[j] > dis[f]+w[i]){
dis[j] = dis[f] + w[i];
cnt[j]=cnt[f]+1;
if(cnt[j]>=n) return 1;
if(!vis[j]){
vis[j] = 1;
q.push(j);
}
}
}
}return 0;
}
int main(){
fill(dis,dis+N,inf);
fill(now,now+N,-1);
cin>>n>>m;
for(int i = 0; i < m;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
if(spfa()){
cout<<"Yes"<<endl;
}
else cout<<"No"<<endl;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
static int n;
static int m;
static int N = 2010;
static int M = 10010;
static int[] h = new int[N];
static int[] e = new int[M];
static int[] ne = new int[M];
static int[] w = new int[M];
static int idx = 0;
static int[] dist = new int[N];//记录虚拟点到x的最短距离
static int[] cnt = new int[N];//从虚拟点到x经过的边数
static boolean[] st = new boolean[N];
public static void add(int a,int b,int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx ++;
}
public static boolean spfa(){
Queue<Integer> queue = new LinkedList<Integer>();
//将所有点进入队列
for(int i = 1;i <= n;i++){
queue.add(i);
st[i] = true;
}
while(!queue.isEmpty()){
int t = queue.poll();
st[t] = false;
for(int i = h[t]; i != -1;i = ne[i]){
int j = e[i];
if(dist[j] > dist[t] + w[i]){
dist[j] = dist[t] + w[i];
cnt[j] = cnt[t] + 1;
if(cnt[j] >= n) return true;
if(!st[j]){
queue.add(j);
st[j] = true;
}
}
}
}
return false;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] str1 = reader.readLine().split(" ");
n = Integer.parseInt(str1[0]);
m = Integer.parseInt(str1[1]);
Arrays.fill(h, -1);
while(m -- > 0){
String[] str2 = reader.readLine().split(" ");
int a = Integer.parseInt(str2[0]);
int b = Integer.parseInt(str2[1]);
int c = Integer.parseInt(str2[2]);
add(a,b,c);
}
if(spfa()) System.out.println("Yes");
else System.out.println("No");
}
}
java参考作者:Acwing小呆呆