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;
}
posted @ 2018-01-21 11:33  XSamsara  阅读(103)  评论(0编辑  收藏  举报