题目描述
小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;
}