负环

传送门

 

来自题解:https://www.luogu.org/wiki/show?name=题解+P3385

 

1.Bellman-Ford

通过Belman-Ford求出最短路,然后在进行一遍松弛操作,如果可以再松弛说明存在负环,否则不存在。

 

2.SPFA

SPFA有两种实现方法。一个是BFS一个是DFS。

 

1.BFS

  BFS版的判断标准:是否存在某个节点入队超过n次

  BFS_SPFA的期望时间复杂度是O(ke),其中k为所有顶点进队的平均次数。

  如果存在负环嘛,这个期望的时间复杂度就真的是期望了。

 

2.DFS

  DFS版判断标准:否存在一点在一条路径上出现多次来判断。

  时间复杂度如果没记错是O(nlogn)的。

 

3.DFS优化

  既然我们只需要判断负环,那么就相当于我们需要找到一条权值和为负的回路。 

  既然我们只需要找到权值和为负的回路,那不妨使距离数组d初始化为0。

  这样处理后,第一次拓展只会拓展到与起点相连边权为负的边。

  那么我们就分别枚举所有的点作为起点,如果已经找到一个负环就不再继续枚举。

  根据SPFA,我们找到的负环一定包含当前枚举的这个点。(因为这个点出现了两次啊)

 

 ——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 using namespace std;
 5 
 6 const int MAXN = 400001;
 7 int T, n, m, cnt;
 8 int head[MAXN], to[MAXN], next[MAXN], val[MAXN], dis[MAXN];
 9 bool vis[MAXN], flag;
10 
11 inline void add(int x, int y, int z)
12 {
13     to[cnt] = y;
14     val[cnt] = z;
15     next[cnt] = head[x];
16     head[x] = cnt++;
17 }
18 
19 inline void spfa(int u)
20 {
21     int i, v;
22     vis[u] = 1;
23     for(i = head[u]; i != -1; i = next[i])
24     {
25         v = to[i];
26         if(dis[u] + val[i] < dis[v])
27         {
28             dis[v] = dis[u] + val[i];
29             if(vis[v])
30             {
31                 flag = 1;
32                 return;
33             }
34             else spfa(v);
35         }
36     }
37     vis[u] = 0;
38 }
39 
40 int main()
41 {
42     int i, x, y, z;
43     scanf("%d", &T);
44     while(T--)
45     {
46         scanf("%d %d", &n, &m);
47         cnt = flag = 0;
48         memset(vis, 0, sizeof(vis));
49         memset(dis, 0, sizeof(dis));
50         memset(head, -1, sizeof(head));
51         for(i = 1; i <= m; i++)
52         {
53             scanf("%d %d %d", &x, &y, &z);
54             add(x, y, z);
55             if(z >= 0) add(y, x, z);
56         }
57          for(i = 1; i <= n && !flag; i++)    spfa(i);
58          if(flag) printf("YE5\n");
59          else printf("N0\n");
60     }
61     return 0;
62 }
View Code

 

posted @ 2017-05-05 09:37  zht467  阅读(163)  评论(0)    收藏  举报