[luoguP1993] 小 K 的农场(差分约束 + spfa 判断负环)

传送门

 

差分约束系统。。找负环用spfa就行

 

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 100001
 5 
 6 int n, m, cnt;
 7 int head[N], to[N << 1], val[N << 1], next[N << 1], dis[N];
 8 bool vis[N];
 9 
10 inline int read()
11 {
12     int x = 0, f = 1;
13     char ch = getchar();
14     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
15     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
16     return x * f;
17 }
18 
19 inline void add(int x, int y, int z)
20 {
21     to[cnt] = y;
22     val[cnt] = z;
23     next[cnt] = head[x];
24     head[x] = cnt++;
25 }
26 
27 inline bool spfa(int u)
28 {
29     int i, v;
30     vis[u] = 1;
31     for(i = head[u]; i ^ -1; i = next[i])
32     {
33         v = to[i];
34         if(dis[v] > dis[u] + val[i])
35         {
36             dis[v] = dis[u] + val[i];
37             if(vis[v]) return 0;
38             else if(!spfa(v)) return 0;
39         }
40     }
41     vis[u] = 0;
42     return 1;
43 }
44 
45 int main()
46 {
47     int i, j, opt, x, y, z;
48     n = read();
49     m = read();
50     memset(head, -1, sizeof(head));
51     for(i = 1; i <= m; i++)
52     {
53         opt = read();
54         x = read();
55         y = read();
56         if(opt == 3) add(x, y, 0), add(y, x, 0);
57         else
58         {
59             z = read();
60             if(opt == 1) add(x, y, -z);
61             if(opt == 2) add(y, x, z);
62         }
63     }
64     memset(dis, 127 / 3, sizeof(dis));
65     for(i = 1; i <= n; i++) add(0, i, 0);
66     dis[0] = 0;
67     spfa(0) ? puts("Yes") : puts("No");
68     return 0;
69 }
View Code

 

posted @ 2017-06-16 14:37  zht467  阅读(128)  评论(0编辑  收藏  举报