BZOJ 3436: 小K的农场【差分约束】
3436: 小K的农场
Time Limit: 10 Sec Memory Limit: 128 MB
Description
背景
小K是个特么喜欢玩MC的孩纸。。。
描述
小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得
一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多
多种植了c个单位的作物,农场a与农场b种植的作物数一样多。但是,由于小K的记忆有些偏差,所以他想要知道存
不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。
Input
第一行包括两个整数n和m,分别表示农场数目和小K记忆中的信息的数目接下来m行:如果每行的第一个数是1,接
下来有三个整数a,b,c,表示农场a比农场b至少多种植了c个单位的作物如果每行第一个数是2,接下来有三个整数a
,b,c,表示农场a比农场b至多多种植了c个单位的作物如果每行第一个数是3,接下来有两个整数a,b,表示农场a
种植的数量与b一样。1<=n,m,a,b,c<=10000
Output
如果存在某种情况与小K的记忆吻合,输出”Yes”,否则输出”No”
Sample Input
3 3
3 1 2
1 1 3 1
2 2 3 2
Sample Output
Yes
样例解释
三个农场种植的数量可以为(2,2,1)
HINT
Source
Kpmcup#0 By Greens
题解
这题就是典型的差分约束,
如果t=1,可得b+c<=a,变式得b-a<=-c;
如果t=2,可得b+c>=a,变式得a-b<=c;
如果t=3,可得b=a,变式得b-a=0,可以写成b-a<=0;
然后可以建边,SPFA判负环。
代码如下:
>#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 10005
using namespace std;
int n,e,dst[MAXN];
bool ans,vis[MAXN];
struct xcw{
int lnk[MAXN],son[MAXN],nxt[MAXN],w[MAXN],tot;
void add(int x,int y,int z){son[++tot]=y;w[tot]=z;nxt[tot]=lnk[x];lnk[x]=tot;}
}a;
void SPFA(int x){
vis[x]=1;
for(int j=a.lnk[x];j;j=a.nxt[j])
if(dst[a.son[j]]>dst[x]+a.w[j]){
dst[a.son[j]]=dst[x]+a.w[j];
if(vis[a.son[j]]){ans=1;break;}
SPFA(a.son[j]);
}
vis[x]=0;
}
int main(){
scanf("%d%d",&n,&e);
for(int i=1,t;i<=e;i++){
scanf("%d",&t);
int x,y,z;
scanf("%d%d",&x,&y);
if(t==1) scanf("%d",&z),a.add(x,y,-z);else
if(t==2) scanf("%d",&z),a.add(y,x,z);else
if(t==3) a.add(x,y,0);
}
memset(dst,63,sizeof(dst));
for(int i=1;i<=n;i++) dst[i]=0,SPFA(i);
if(ans) printf("No\n");else printf("Yes\n");
return 0;
}