spfa判负环

输入输出格式

输入格式:

第一行一个正整数T表示数据组数,对于每组数据:

第一行两个正整数N M,表示图有N个顶点,M条边

接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)

输出格式:

共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。

输入输出样例

输入样例#1: 
2
3 4
1 2 2
1 3 4
2 3 1
3 1 -3
3 3
1 2 3
2 3 4
3 1 -8
输出样例#1: 
N0
YE5

说明

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 }
View Code

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 }
View Code
原文地址:https://www.cnblogs.com/adelalove/p/8492193.html