首先这是个查分约束系统。。。(那是啥来着←_←)
然后判断可行解的话,直接spfa判负圈。
bfs版spfa要记录每个点的进队次数,如果大于点数就代表有负圈。。。但是好慢Σ( ° △ °|||)︴
于是改用dfs版的spfa(还以为会很慢。。。,其实速度极快Orz)
1 /************************************************************** 2 Problem: 3436 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:36 ms 7 Memory:1236 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 12 using namespace std; 13 const int N = 10005; 14 const int M = N; 15 const int Maxlen = 20 * M; 16 17 struct edges { 18 int next, to, v; 19 edges() {} 20 edges(int _n, int _t, int _v) : next(_n), to(_t), v(_v) {} 21 } e[M]; 22 23 int n, m; 24 int first[N], tot; 25 int d[N]; 26 int v[N], flag; 27 char buf[Maxlen], *c = buf; 28 int Len; 29 30 inline int read() { 31 int x = 0; 32 while (*c < '0' || '9' < *c) ++c; 33 while ('0' <= *c && *c <= '9') 34 x = x * 10 + *c - '0', ++c; 35 return x; 36 } 37 38 inline void add_edge(int x, int y, int z) { 39 e[++tot] = edges(first[x], y, z); 40 first[x] = tot; 41 } 42 43 void spfa(int p) { 44 if (v[p]) { 45 flag = 1; 46 return; 47 } 48 int x, y; 49 v[p] = 1; 50 for (x = first[p]; x; x = e[x].next) 51 if (d[p] + e[x].v < d[y = e[x].to]) { 52 d[y] = d[p] + e[x].v; 53 spfa(y); 54 if (flag) return; 55 } 56 v[p] = 0; 57 } 58 59 int main() { 60 Len = fread(c, 1, Maxlen, stdin); 61 buf[Len] = '\0'; 62 int i, oper, x, y, z; 63 n = read(), m = read(); 64 for (i = 1; i <= m; ++i) { 65 oper = read(), x = read(), y = read(); 66 if (oper == 3) add_edge(x, y, 0); 67 else { 68 z = read(); 69 if (oper == 1) add_edge(x, y, -z); 70 else add_edge(y, x, z); 71 } 72 } 73 for (i = 1; i <= n; ++i) { 74 spfa(i); 75 if (flag) break; 76 } 77 puts(flag ? "No" : "Yes"); 78 return 0; 79 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen