小K的农场

51 篇文章 0 订阅
7 篇文章 0 订阅

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

.
.
.
.
.
分析
差分约束
用dfs模拟spfa

.
.
.
.
.
.
程序:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int head[100000],cnt=0,dis[20000];
bool f[100000];

struct edge
{
	int to,from,w;
} t[100000];

void add(int x,int y,int z)
{
	t[++cnt].to=y;t[cnt].from=head[x];t[cnt].w=z;head[x]=cnt;
}

bool spfa(int x)
{
	f[x]=true;
	for (int i=head[x];i;i=t[i].from)
	{
		int u=t[i].to;
		if (dis[x]+t[i].w>dis[u])
		{
			dis[u]=dis[x]+t[i].w;
			if (f[u]==true) return false;
			if (spfa(u)==false) return false;
		}
	}
	f[x]=false;
    return true;
}

int main()
{
	int n,m; 
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int w,a,b,c;
		scanf("%d",&w);
		if (w==1)
		{
			scanf("%d%d%d",&a,&b,&c);
			add(b,a,c);
		} else
		if (w==2)
		{
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,-c);
		} else
		if (w==3)
		{
			scanf("%d%d",&a,&b);
			add(a,b,0);
			add(b,a,0);
		}
	}
	
	for (int i=1;i<=n;i++)
	{
		add(0,i,0);
		dis[i]=-2147483647;
	}
	if (spfa(0)==false) printf("No"); else printf("Yes");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值