bellman-ford判负环,据bellman-ford的性质最后得出的是通过不超过n-1条边的从起点到其他点的最短距离(因为n个点,所以n-1条边)
但是如果在n-1次循环之后仍然存在边可以被松弛,那么就存在负环(因为如果没有负环n-1次就已经确定了最短距离,具体可参考bellman-ford证明,已经是最短距离了还能被松弛,必然是存在负环)
1 #include<iostream> 2 using namespace std; 3 const int N=2010,M=1e5+10; 4 int n,m; 5 struct edge{ 6 int a,b,w; 7 }edges[M]; 8 int dis[N]; 9 void bellman_ford(){ 10 //直接把dis初始化为全0就可以了,意思就是所有的点都是起点 11 for(int i=0;i<n-1;i++){ 12 for(int j=0;j<m;j++){ 13 auto t=edges[j]; 14 if(dis[t.b]>dis[t.a]+t.w){ 15 dis[t.b]=dis[t.a]+t.w; 16 } 17 } 18 } 19 } 20 int main(void){ 21 cin>>n>>m; 22 for(int i=0;i<m;i++){ 23 int a,b,c; 24 cin>>a>>b>>c; 25 edges[i]={a,b,c}; 26 } 27 bellman_ford(); 28 for(int j=0;j<m;j++){ 29 auto t=edges[j]; 30 if(dis[t.b]>dis[t.a]+t.w){ 31 cout<<"Yes"; 32 return 0; 33 } 34 } 35 cout<<"No"; 36 return 0; 37 }
spfa判负环
1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 const int N=2010,M=1e5+10; 6 int n,m; 7 int h[N],e[M],w[M],ne[M],idx; 8 int dis[N],cnt[N]; 9 bool st[N]; 10 void add(int a,int b,int c){ 11 e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++; 12 } 13 bool spfa(){ 14 queue<int> q; 15 for(int i=1;i<=n;i++){ 16 q.push(i); 17 st[i]=true; 18 }//把所有的点都丢进队列里面 19 while(q.size()){ 20 int t=q.front(); 21 q.pop(); 22 st[t]=false; 23 for(int i=h[t];i!=-1;i=ne[i]){ 24 int j=e[i]; 25 if(dis[j]>dis[t]+w[i]){ 26 dis[j]=dis[t]+w[i]; 27 cnt[j]=cnt[t]+1; 28 if(cnt[j]>=n){ 29 return true; 30 } 31 if(!st[j]){ 32 q.push(j); 33 st[j]=true; 34 } 35 } 36 } 37 } 38 return false; 39 } 40 int main(void){ 41 cin>>n>>m; 42 memset(h,-1,sizeof(h)); 43 for(int i=0;i<m;i++){ 44 int a,b,c; 45 cin>>a>>b>>c; 46 add(a,b,c); 47 } 48 if(spfa()){ 49 cout<<"Yes"; 50 }else{ 51 cout<<"No"; 52 } 53 return 0; 54 }