题目描述
小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。
思路
源自:five20
代码
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=50010,oo=1e9; bool vis[N]; int n,m,tot; int to[N],hed[N],w[N]; int sum[N],dis[N],nxt[N]; void add(int u,int v,int c) { to[++tot]=v; nxt[tot]=hed[u]; hed[u]=tot; w[tot]=c; } bool spfa(int u) { vis[u]=1; for(int i=hed[u]; i; i=nxt[i]) if(dis[to[i]]<dis[u]+w[i]) { dis[to[i]]=dis[u]+w[i]; if(vis[to[i]]) return false; if(!spfa(to[i])) return false; } vis[u]=0; return true; } int main () { scanf("%d%d",&n,&m); int f,u,v,w; while(m--) { scanf("%d%d%d",&f,&u,&v); if(f==1) { scanf("%d",&w); add(u,v,w); } if(f==2) { scanf("%d",&w); add(u,v,-w); } if(f==3) { add(u,v,0); add(v,u,0); } } for(int i=1; i<=n; i++) { add(0,i,0); dis[i]=-oo; } if(!spfa(0)) printf("No\n"); else printf("Yes\n"); return 0; }