BZOJ3436 小K的农场
Posted ljh2000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3436 小K的农场相关的知识,希望对你有一定的参考价值。
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
3 1 2
1 1 3 1
2 2 3 2
Sample Output
Yes
样例解释
三个农场种植的数量可以为(2,2,1)
样例解释
三个农场种植的数量可以为(2,2,1)
HINT
Source
正解:差分约束系统
解题报告:
这道题就是一道差分约束系统裸题。
好久没做差分约束系统的题我都快忘了怎么连边了...首先如果x-y<=z,那么显然y的值到x的值必须要把差控制在z以内,所以应该是y向x连边,边权为z;如果是x-y>=z,那么,显然是转成y-x<=-z,所以x向y连一条-z的边(一般都习惯以小于号为主体)。所以我们只要找负权环就可以了。
相等的时候并不用考虑,直接连一条边权为0的边即可,一条两条随意。
当然,找负权环,dfs版SPFA肯定要优秀一些。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long LL; 15 const int MAXN = 10011; 16 const int MAXM = 20011; 17 int n,m,ecnt,top; 18 int first[MAXN],to[MAXM],next[MAXM],w[MAXM],dis[MAXN]; 19 int stack[MAXN],cnt[MAXN]; 20 bool in[MAXN]; 21 22 inline int getint() 23 { 24 int w=0,q=0; char c=getchar(); 25 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar(); 26 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); return q ? -w : w; 27 } 28 inline void link(int x,int y,int z){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; w[ecnt]=z; } 29 inline bool SPFA(){ 30 for(int i=1;i<=n;i++) dis[i]=0,stack[++top]=i,in[i]=1; 31 int u; 32 while(top>0) { 33 u=stack[top]; top--; in[u]=0; 34 for(int i=first[u];i;i=next[i]) { 35 int v=to[i]; 36 if(dis[v]>dis[u]+w[i]) { 37 dis[v]=dis[u]+w[i]; 38 if(!in[v]) { in[v]=1; stack[++top]=v; cnt[v]++; if(cnt[v]>=n) return false;} 39 } 40 } 41 } 42 return true; 43 } 44 45 inline void work(){ 46 n=getint(); m=getint(); int x,y,z,ljh; 47 for(int i=1;i<=m;i++) { 48 ljh=getint(); x=getint(); y=getint(); 49 if(ljh==1) z=getint(),link(x,y,-z); 50 else if(ljh==2) z=getint(),link(y,x,z); 51 else link(x,y,0); 52 } 53 if(SPFA()) printf("Yes"); else printf("No"); 54 } 55 56 int main() 57 { 58 work(); 59 return 0; 60 }
以上是关于BZOJ3436 小K的农场的主要内容,如果未能解决你的问题,请参考以下文章