[附中OJ 1491]小K的农场

来源:互联网 发布:mac怎么卸载adobe 编辑:程序博客网 时间:2024/04/29 11:05

题目描述

小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多多种植了c个单位的作物,农场a与农场b种植的作物数一样多。但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

输入

第一行包括两个整数n和m,分别表示农场数目和小K记忆中的信息数目。

接下来m行:

如果每行的第一个数是1,接下来有3个整数a,b,c,表示农场a比农场b至少多种植了c个单位的作物。如果每行的第一个数是2,接下来有3个整数a,b,c,表示农场a比农场b至多多种植了c个单位的作物。如果每行的第一个数是3,接下来有2个整数a,b,表示农场a种植的作物数量和b一样多。

输出

如果存在某种情况与小K的记忆吻合,输出“Yes”,否则输出“No”。

样例输入

3 33 1 21 1 3 12 2 3 2

样例输出

Yes

提示

样例解释:三个农场种植数量可以为(2,2,1)。
对于100%的数据 1<=n,m,a,b,c<=10000.

题解:查分约束系统。spfa判环。
代码:

#include<iostream>#include<queue>#include<cstdio>#include<cstdlib>#include<algorithm>#define INF 199912270000ll#define LiangJiaJun mainusing namespace std;const int S = 0 ,  T = 10001;int n,m;int h[10004],ne=1;struct edge{    int to,next;long long w;}e[120004];bool vis[10004];long long dis[10004];void insert(int u,int v,long long w){    e[++ne].to = v; e[ne].w = w; e[ne].next = h[u];    h[u]= ne;}bool ok=1;void spfa(int x){     if(vis[x]){ok=0;return ;}     vis[x]=1;     for(int i=h[x];i;i=e[i].next){        if(dis[e[i].to] < dis[x] + e[i].w){           dis[e[i].to] = dis[x] + e[i].w;           spfa(e[i].to);        }        if(!ok)return;     }     vis[x]=0;}int LiangJiaJun (){    scanf("%d%d",&n,&m);    for(int i=0;i<=10002;i++) dis[i]=-INF;    for(int i=1;i<=n;i++) insert(S,i,1);    for(int i=1;i<=m;i++){        int t,a,b; long long c;        scanf("%d%d%d",&t,&a,&b);        if(t == 1){            scanf("%lld",&c);            if(a==b)return puts("No"),0;            insert(b,a,c);        }        if(t == 2){            scanf("%lld",&c);            if(a==b)return puts("No"),0;            insert(a,b,-c);        }        if(t == 3){            insert(a,b,0);            insert(b,a,0);        }    }    for(int i=1;i<=n;i++){        spfa(i);        if(!ok)break;    }    if(ok)puts("Yes");    else puts("No");    return 0;}