小K的农场

小K的农场

题目描述

小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”。

输入输出样例

输入样例#1:

3 3
3 1 2
1 1 3 1
2 2 3 2

输出样例#1:

Yes

说明

对于 100% 的数据保证:(1 ≤ n,m,a,b,c ≤ 10000.)

题解

看到题目中的三个条件,应该可以看出这是一道差分约束题了

首先抛开题目,如果一个式子满足

[dis[j]>=dis[i]+w[i,j] ]

应该可以想到最长路的三角不等式

对于一条边(u,v,w),我们认为v点的值需要至少比u点大w

所以对于1条件,可以简化为(dis[a]>=dis[b]+c),我们建一条由b到a的边,边权为c

对于2条件,(dis[a]<=dis[b]+c),转化为(dis[b]>=dis[a]-c),建一条由a到b的边,边权为-c

对于3条件,(dis[a]=dis[b]),建双向边(a,b),边权为0

其次,为了保证图联通,我们吧每个节点向0点建一条边权为0的边
所以数组就要开3倍!!!!!

然后跑最短路就可以了,SPFA判环,最长路判正环,最短路判负环,没什么要注意的了

Code

#include<bits/stdc++.h>
#define rg register
#define Min(a,b) (a)<(b)?(a):(b)
using namespace std;
const int N=10010,M=10010;
const int inf=2e9;

int in(int &ans)
{
    ans=0; int f=1; char i=getchar();
    while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
    while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0', i=getchar();
    ans*=f;
}

bool flag;
int cnt,n,m,T;
int to[M<<2],nex[M<<2],w[M<<2],head[N],dis[N],vis[N];

inline void add(int a,int b,int c)
{
    to[++cnt]=b,nex[cnt]=head[a];
    w[cnt]=c,head[a]=cnt;
}

void SPFA(int u)
{
    vis[u]=1;
    for(int i=head[u];i;i=nex[i]) {
	if(dis[to[i]]<dis[u]+w[i]) {
	    if(vis[to[i]]||flag) {flag=1;break;}
	    dis[to[i]]=dis[u]+w[i];
	    SPFA(to[i]);
	}
    }vis[u]=0;
}

int main()
{
    in(n),in(m);
    for(int i=1;i<=m;i++) {
	int op,a,b,c;
	in(op);
	switch(op){
	case 1:in(a),in(b),in(c),add(b,a,c);break;
	case 2:in(a),in(b),in(c),add(a,b,-c);break;
	case 3:in(a),in(b),add(a,b,0),add(b,a,0);break;
	}
    }
    for(int i=1;i<=n;i++) add(0,i,0);
    for(int i=1;i<=n;i++) dis[i]=-inf;
    SPFA(0); puts((!flag)?"Yes":"No");
    return 0;
}

博主蒟蒻,随意转载.但必须附上原文链接

http://www.cnblogs.com/real-l/

原文地址:https://www.cnblogs.com/real-l/p/9547725.html