题目描述
小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述:
- 农场a比农场b至少多种植了c个单位的作物,
- 农场a比农场b至多多种植了c个单位的作物,
- 农场a与农场b种植的作物数一样多。
但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。
输入格式
第一行包括两个整数 n 和 m,分别表示农场数目和小 K 记忆中的信息数目。
接下来 m 行:
如果每行的第一个数是 1,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至少多种植了 c 个单位的作物。
如果每行的第一个数是 2,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至多多种植了 c 个单位的作物。如果每行的第一个数是 3,接下来有 2 个整数 a,b,表示农场 a 种植的的数量和 b 一样多。
输出格式
如果存在某种情况与小 K 的记忆吻合,输出“Yes”,否则输出“No”。
输入输出样例
输入 #1
3 3 3 1 2 1 1 3 1 2 2 3 2
输出 #1
Yes
说明/提示
对于 100% 的数据保证:1 ≤ n,m,a,b,c ≤ 10000。
思路
差分约束,有三种情况
1、a - b >= c, 连正边
2、a - b <= c, 连反边
3、a - b = 0, 边权为0,且是 a -> b = b -> a = 0;
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5 6 using namespace std; 7 typedef long long LL; 8 9 template<class T>inline void read(T &res) 10 { 11 char c;T flag=1; 12 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 13 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 14 } 15 16 namespace _buff { 17 const size_t BUFF = 1 << 19; 18 char ibuf[BUFF], *ib = ibuf, *ie = ibuf; 19 char getc() { 20 if (ib == ie) { 21 ib = ibuf; 22 ie = ibuf + fread(ibuf, 1, BUFF, stdin); 23 } 24 return ib == ie ? -1 : *ib++; 25 } 26 } 27 28 int qread() { 29 using namespace _buff; 30 int ret = 0; 31 bool pos = true; 32 char c = getc(); 33 for (; (c < '0' || c > '9') && c != '-'; c = getc()) { 34 assert(~c); 35 } 36 if (c == '-') { 37 pos = false; 38 c = getc(); 39 } 40 for (; c >= '0' && c <= '9'; c = getc()) { 41 ret = (ret << 3) + (ret << 1) + (c ^ 48); 42 } 43 return pos ? ret : -ret; 44 } 45 46 const int maxn = 1e4 + 7; 47 const int inf = 0x3f3f3f3f; 48 49 int n,m; 50 51 int head[maxn << 1], edge[maxn << 1], nxt[maxn << 1]; 52 int c[maxn << 1]; 53 int cnt; 54 int dis[maxn], in[maxn]; 55 bool vis[maxn]; 56 57 void BuildGraph(int u, int v, int w) { 58 cnt++; 59 edge[cnt] = v; 60 nxt[cnt] = head[u]; 61 c[cnt] = w; 62 head[u] = cnt; 63 } 64 65 bool spfa(int u) { 66 //memset(dis, -1, sizeof(dis)); 67 vis[u] = 1; 68 dis[u] = 0; 69 in[u] = 1; 70 queue <int> q; 71 q.push(u); 72 while(!q.empty()) { 73 u = q.front(); 74 q.pop(); 75 vis[u] = 0; 76 for (int i = head[u]; i ; i = nxt[i]) { 77 int v = edge[i]; 78 int w = c[i]; 79 if(dis[v] < dis[u] + w) { 80 dis[v] = dis[u] + w; 81 if(!vis[v]) { 82 q.push(v); 83 vis[v] = 1; 84 ++in[v]; 85 if(in[v] > n + 1) { 86 return true; 87 } 88 } 89 } 90 } 91 } 92 return false; 93 } 94 95 int main() 96 { 97 scanf("%d %d",&n, &m); 98 for ( int i = 1; i <= m; ++i ) { 99 int opt; 100 int u, v, w; 101 scanf("%d",&opt); 102 if(opt == 1) { 103 scanf("%d %d %d",&u, &v, &w); 104 BuildGraph(u, v, w); 105 } 106 else if(opt == 2) { 107 scanf("%d %d %d",&u, &v, &w); 108 BuildGraph(u, v, -w); 109 } 110 else { 111 scanf("%d %d",&u, &v); 112 BuildGraph(u, v, 0); 113 BuildGraph(v, u, 0); 114 } 115 } 116 for ( int i = 1; i <= n; ++i ) { 117 BuildGraph(0, i, 0); 118 dis[i] = -inf; 119 } 120 if(spfa(0)) { 121 puts("No"); 122 } 123 else { 124 puts("Yes"); 125 } 126 return 0; 127 }