判負環(bellman-ford | | spfa)
阿新 • • 發佈:2020-11-19
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 }