洛谷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 }
时间: 2024-10-14 17:56:03

洛谷P3385 【模板】负环 DFS-SPFA 判负环 图论的相关文章

洛谷—— P3385 【模板】负环

题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向) 输出格式: 共T行.对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号). 输入输出样例 输入样例#1: 2 3 4 1

poj3259 Wormholes --- spfa判负环

又写了个bellman模板一直RE求解啊... #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x

Poj3259--Wormholes(Spfa 判负环)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36836   Accepted: 13495 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

LightOj 1221 - Travel Company(spfa判负环)

1221 - Travel Company PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB A travel company is planning to launch their bus service in a new route. So they conducted a survey and made a list of all possible roads connecting diff

uva11090 Going in Cycle!! --- 二分+spfa判负环

给一个带权有向图,求其中是否存在环,若存在,输出环上边权的平均值最小的那个的平均值. 点的范围就50,感觉可以很暴力..但显然超时了 感觉方法好巧妙,二分平均值,将所有边权减去二分的那个值,然后spfa判断是否有负环 若有负环,则图中存在的所有环的边权平均值一定比枚举值大 反之则小,要是无论枚举值多大都没有负环,说明图中没有环. #include <iostream> #include <cstring> #include <string> #include <c

POJ-1860 Currency Exchange 【spfa判负环】

Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the

POJ 3259 Wormholes(SPFA判负环)

题目链接:http://poj.org/problem?id=3259 题目大意是给你n个点,m条双向边,w条负权单向边.问你是否有负环(虫洞). 这个就是spfa判负环的模版题,中间的cnt数组就是记录这个点松弛进队的次数,次数超过点的个数的话,就说明存在负环使其不断松弛. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using na

spfa判负权边

spfa判负环 如果一个点在spfa中被入队了大于n次 那么,我们就能肯定,有负环出现. 因为一个点入队时,他肯定被更新了一次. 所以........ 如果不存在负权环.这个点最多被更新节点数次 我们就可以利用这个性质判负环 亏我dijk写了一上午 题目 语文模板题 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<queue> u

POJ 1860——Currency Exchange——————【最短路、SPFA判正环】

Currency Exchange Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1860 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two par