1. 程式人生 > >洛谷P3385 【模板】負環 DFS-SPFA 判負環 圖論

洛谷P3385 【模板】負環 DFS-SPFA 判負環 圖論

string inf scan space can 清空 span %d pre

洛谷P3385 【模板】負環

圖論

今天get了 一個 DFS-SPFA 判負環的方法

一般的 BFS-SPFA 判負環 一般就是 不停地做,如果某點第 n+1次加入隊列中,那麽說明這個圖存在負環
然而我並不會證明,期望復雜度是 O(kM) k 大約是在 2 左右 但是其實對於一些極限數據,最壞可以
把他卡到 O( NM) 額,這就直接炸飛了是不是,而且據說,一些數據比較強的題目,總會想到卡一卡SPFA
的,

然後我們換一種思路
因為題目中一定存在一種 負環對吧,所以說假如你某段路徑權值和為自然數的時候, 你這一段還不如
不走對不對,你還不如直接從第一條負邊開始走起,
我們把每個點的 dist設為 0 ,dfs下去如果能夠松弛的話就一直松弛下去,這時候的松弛還有另一個含義
,因為你設的每個的dist是 0 ,所以能夠松弛還說明的到 從起點 s 到這個點的 路徑和一直是 負的,
我們把在這條路徑中的點標記一下,如果下次 有松弛過的點 到這個點,那麽說明就有負環

另外 要註意從每一個點開始的 DFS-SPFA 求的只是求的 以他為起點的 負環是否存在,因為 每次dfs
如果碰到 不能松弛就不 松弛了,那麽也許後面還能夠松弛,所以說要枚舉每一個點作為松弛起點



另外註意這題的坑點 YE‘5‘ 和 N‘0‘ 不包括引號
然後 註意一下初始化 邊表 head 以及cnt 都要清空

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <string
> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std ; 10 11 const int maxn = 200011,maxm = 200011,inf = 1e9 ; 12 struct node{ 13 int to,val,pre ; 14 }e[2*maxm]; 15 int T,n,m,x,y,val,cnt ; 16 int head[maxn],dist[maxn] ; 17 bool flag ;
18 bool vis[maxn] ; 19 20 inline void addedge(int x,int y,int v) 21 { 22 e[++cnt] = (node){ y,v,head[x] } ; 23 head[ x ] = cnt ; 24 } 25 26 inline int read() 27 { 28 char ch = getchar() ; 29 int x = 0 , f = 1 ; 30 while(ch<0||ch>9) { if(ch==-) f = -1 ; ch = getchar() ; } 31 while(ch>=0&&ch<=9) { x = x*10+ch-48 ; ch = getchar() ; } 32 return x*f ; 33 } 34 35 inline void SPFA(int u) 36 { 37 int v ; 38 vis[ u ] = 1 ; 39 for(int i=head[u];i;i = e[ i ].pre ) 40 { 41 v = e[ i ].to ; 42 if( dist[ u ] + e[ i ].val < dist[ v ] ) 43 { 44 dist[ v ] = dist[ u ] + e[ i ].val ; 45 if(vis[ v ]||flag) 46 { 47 flag = 1 ; 48 break ; 49 } 50 SPFA( v ) ; 51 } 52 } 53 vis[ u ] = 0 ; 54 } 55 56 int main() 57 { 58 T = read() ; 59 while(T--) 60 { 61 flag = 0 ; 62 cnt = 0 ; 63 n = read() ; m = read() ; 64 for(int i=1;i<=n;i++) dist[ i ] = 0,vis[ i ] = 0,head[ i ] = 0 ; //0 65 for(int i=1;i<=m;i++) 66 { 67 scanf("%d%d%d",&x,&y,&val) ; 68 addedge(x,y,val) ; 69 if(val>=0) addedge(y,x,val) ; 70 } 71 for(int i=1;i<=n;i++) 72 { 73 SPFA( i ) ; 74 if(flag) break ; 75 } 76 if(flag) 77 printf("YE5\n") ; 78 else 79 printf("N0\n") ; 80 81 } 82 return 0 ; 83 }

洛谷P3385 【模板】負環 DFS-SPFA 判負環 圖論