题目描述
小K 是个特么喜欢玩MC 的孩纸。。。
小K 在MC 里面建立很多很多的农场,总共n 个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m 个),以下列三种形式描述:
农场a 比农场b 至少多种植了c 个单位的作物,农场a 比农场b 至多多种植了c 个单位的作物,农场a 与农场b 种植的作物数一样多。但是,由于小K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。
输入
第一行包括两个整数n 和m,分别表示农场数目和小K 记忆中的信息的数目
接下来m 行:
如果每行的第一个数是1,接下来有三个整数a,b,c,表示农场a 比农场b 至少多种植了c 个单位的作物
如果每行第一个数是2,接下来有三个整数a,b,c,表示农场a 比农场b 至多多种植了c 个单位的作物
如果每行第一个数是3,接下来有两个整数a,b,表示农场a 种植的数量与b一样多
输出
如果存在某种情况与小K 的记忆吻合,输出“Yes” ,否则输出“No”
样例输入
3 33 1 21 1 3 12 2 3 2
样例输出
Yes
提示
【样例解释】三个农场种植的数量可以为(2,2,1)。
【数据范围与约定】
对于10%的数据,1 <= n ,m<= 10
对于100%的数据,1 <= n,m,a,b,c <= 10000
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=100005;
const int inf=1000000009;
struct data{
int v,w,nxt;
}e[maxn*2];
int n,m,cnt=0;
int dis[maxn],tim[maxn],fst[maxn];
bool vis[maxn],f=1;
inline int get(){
char c;while(!isdigit(c=getchar()));
int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
return v;
}
inline void add(int x,int y,int z){
e[++cnt].v=y,e[cnt].w=z,e[cnt].nxt=fst[x],fst[x]=cnt;
}
queue<int>q;
inline void spfa(){
dis[n+1]=0;
vis[n+1]=1;
q.push(n+1);
while(!q.empty()){
int x=q.front();q.pop();vis[x]=0;
for(int i=fst[x];i;i=e[i].nxt){
int y=e[i].v;++tim[y];
if(tim[y]>101){f=0;break;}
if(dis[y]>dis[x]+e[i].w){
dis[y]=dis[x]+e[i].w;
if(!vis[y])q.push(y),vis[y]=1;
}
}
if(!f)break;
}
}
int main(){
n=get();m=get();
memset(vis,0,sizeof(vis));
memset(tim,0,sizeof(tim));
for(int i=1;i<=m;++i){
int p=get();
int x,y,z;
if(p==1)x=get(),y=get(),z=get(),add(x,y,-z);
if(p==2)x=get(),y=get(),z=get(),add(y,x,z);
if(p==3)x=get(),y=get(),add(x,y,0),add(y,x,0);
}
for(int i=1;i<=n;++i)add(n+1,i,0),dis[i]=inf;
spfa();
if(f)printf("Yes\n");
else printf("No\n");
return 0;
}
思路:典型的差分约束系统。易知有负环时方案不存在.
注意:(1)由于0边和源点多连了边,所以maxn要开大一点。