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


洛谷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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM