spfa判负环
输入输出格式
输入格式:
第一行一个正整数T表示数据组数,对于每组数据:
第一行两个正整数N M,表示图有N个顶点,M条边
接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)
输出格式:
共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。
输入输出样例
说明
N,M,|w|≤200 000;1≤a,b≤N;T≤10
大提醒:多组数据初始化一定要彻底
1.spfa的BFS形式判负环,但是比较慢,经常会T
思想:如果有一个点入队超过n次,说明存在负环。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #define inf 2147483600 5 using namespace std; 6 const int N=500002; 7 struct node{ 8 int v,c,ne; 9 }e[N*2]; 10 int n,m,tot,h[N]; 11 void add(int u,int v,int c) 12 { 13 tot++;e[tot].v=v;e[tot].c=c;e[tot].ne=h[u];h[u]=tot; 14 } 15 int v[N],d[N],in[N],cnt[N]; 16 queue<int>q; 17 bool fg; 18 void spfa(int s) 19 { 20 for(int i=1;i<=n;i++) d[i]=inf,v[i]=0; 21 v[s]=1;d[s]=0;q.push(s); 22 while(!q.empty()) 23 { 24 int ff=q.front();q.pop();v[ff]=0; 25 in[ff]=1;cnt[ff]++; 26 if(cnt[ff]>=n+1){fg=1;return;} 27 for(int i=h[ff];i;i=e[i].ne) 28 { 29 int rr=e[i].v; 30 if(d[rr]>d[ff]+e[i].c) 31 { 32 d[rr]=d[ff]+e[i].c; 33 if(!v[rr]) 34 v[rr]=1,q.push(rr); 35 } 36 } 37 } 38 } 39 int T; 40 int main() 41 { 42 scanf("%d",&T); 43 while(T--) 44 { 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=n;++i) h[i]=in[i]=cnt[i]=0; 47 tot=0;fg=0; 48 for(int i=1;i<=m;i++) 49 { 50 int x,y,z;scanf("%d%d%d",&x,&y,&z); 51 add(x,y,z); 52 if(z>0) add(y,x,z); 53 } 54 for(int i=1;i<=n;++i) 55 { 56 if(!in[i]) spfa(i); 57 if(fg) break; 58 } 59 if(!fg)cout<<"N0"<<endl; 60 else cout<<"YE5"<<endl; 61 } 62 return 0; 63 }
2.spfa的DFS形式判负环,比BFS要快很多
思想:初始化,d[i]=0;枚举每个点去找负环
再进行松弛操作的同时如果一个点被松弛到两次,说明存在负环。
因为初始dis为0,所以只能通过负边来更新d[],而一但一个点被松弛了多次,那么一定存在负环。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #define inf 2147483600 5 using namespace std; 6 const int N=500002; 7 struct node{ 8 int v,c,ne; 9 }e[N*2]; 10 int n,m,tot,h[N]; 11 void add(int u,int v,int c) 12 { 13 tot++;e[tot].v=v;e[tot].c=c;e[tot].ne=h[u];h[u]=tot; 14 } 15 int v[N],d[N],in[N],cnt[N]; 16 queue<int>q; 17 bool fg; 18 void spfa(int u) 19 { 20 if(fg) return; 21 v[u]=1; 22 for(int i=h[u];i;i=e[i].ne) 23 { 24 int rr=e[i].v; 25 if(d[rr]>d[u]+e[i].c) 26 { 27 d[rr]=d[u]+e[i].c; 28 if(v[rr] || fg){fg=1;break;} 29 spfa(rr); 30 } 31 } 32 v[u]=0; 33 } 34 int T; 35 int main() 36 { 37 scanf("%d",&T); 38 while(T--) 39 { 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=n;++i) h[i]=v[i]=0,d[i]=0; 42 tot=0;fg=0; 43 for(int i=1;i<=m;i++) 44 { 45 int x,y,z;scanf("%d%d%d",&x,&y,&z); 46 add(x,y,z); 47 if(z>0) add(y,x,z); 48 } 49 for(int i=1;i<=n;++i) 50 { 51 spfa(i); 52 if(fg) break; 53 } 54 if(!fg)cout<<"N0"<<endl; 55 else cout<<"YE5"<<endl; 56 } 57 return 0; 58 }