1. 程式人生 > >spfa判負環

spfa判負環

fine con 輸出 front 思想 hide break sed OS

輸入輸出格式

輸入格式:

第一行一個正整數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

spfa判負環