[bzoj3436][差分约束]小K的农场

来源:互联网 发布:手机网页聊天室源码 编辑:程序博客网 时间:2024/05/21 07:08

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

HINT

样例解释
三个农场种植的数量可以为(2,2,1)

题解

差分约束一眼题
直接设d[i]为第i个农场种植的作物数
输入x,y,c(c第三种操作可以去掉)
第一种操作 d[y]≥d[x]-c 那么x~y连一条-c的边
第二种操作 d[x]≥d[y]+c 那么y~x连一条c的边
第三种操作 d[x]≥d[y] 且 d[y]≥d[x] 那么x~y和y~x都要一条权为0的边
跑最长路即可,最短路的话吧上面改一下也可以跑。。
记住判环的时候一定要break掉while

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;struct node{    int x,y,c,next;}a[51000];int len,last[51000];void ins(int x,int y,int c){    len++;    a[len].x=x;a[len].y=y;a[len].c=c;    a[len].next=last[x];last[x]=len;}int d[51000];bool v[51000];int sta[51000],top,ru[51000];int n,m;int main(){    scanf("%d%d",&n,&m);    len=0;memset(last,0,sizeof(last));    for(int i=1;i<=m;i++)    {        int x,y,c,op;        scanf("%d%d%d",&op,&x,&y);        if(op==1 || op==2)scanf("%d",&c);        if(op==1)ins(x,y,-c);        else if(op==2)ins(y,x,c);        else ins(y,x,0),ins(x,y,0);    }    memset(d,0,sizeof(d));    memset(ru,0,sizeof(ru));    top=0;memset(v,true,sizeof(v));    for(int i=1;i<=n;i++)sta[++top]=i,ru[i]++;    bool bk=false;    while(top)    {        int x=sta[top--];        v[x]=false;        for(int k=last[x];k;k=a[k].next)        {            int y=a[k].y;            if(d[y]<d[x]+a[k].c)            {                d[y]=d[x]+a[k].c;                ru[y]++;                if(ru[y]>=n){bk=true;break;}                if(v[y]==false)                {                    v[y]=true;                    sta[++top]=y;                }            }        }        if(bk==true)break;//这里一定要break,因为上面那个break只是跳出if的。。     }    if(bk==false)printf("Yes\n");    else printf("No\n");    return 0;}
原创粉丝点击