P1993 小 K 的农场 题解

P1993 小 K 的农场

Description

给你 \(m\) 个形式如下的不等式,让你判断这个 \(n\) 元一次不等式组是否存在合法的正整数解。

  • 1 a b c 表示 \(A_a-A_b\ge c\)

  • 2 a b c 表示 \(A_a-A_b\le c\)

  • 3 a b 表示 \(A_a=A_b\)

Solution

想办法转化一下。

对于操作 1:

\[A_a-A_b\ge c \]

两边同时加 \(A_b\)

\[A_a\ge A_b+c \]

移项成一个差分约束的形式即可。

\[A_b\le A_a-c \]

加边的代码:add_edge(a,b,-c)

同理,操作二可化为 add_edge(b,a,c)

操作三,\(A_a=A_b\)

可以分成两个不等式来看:\(A_a\ge A_b\)\(A_a\le A_b\)

add_edge(a,b,0);
add_edge(b,a,0);

Tips:由于最后一个操作会建两条边,所以最坏情况下边数是 \(2\times m+n\) 的,注意边数组的大小。

#include<bits/stdc++.h>
#define int long long
using namespace std;
long long n,m,tot,head[10005],vis[10005],dis[10005],cnt[10005];
struct node{
	int from,to,w,nxt;
}e[15005];
inline void add_edge(int u,int v,int w){
	e[++tot].from=u;
	e[tot].to=v;
	e[tot].w=w;
	e[tot].nxt=head[u];
	head[u]=tot;
	return;
}
queue<int>q;
inline bool SPFA(){
	memset(dis,63,sizeof(dis));
	dis[0]=0;
	vis[0]=1;
	q.push(0);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to,w=e[i].w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v]){
					vis[v]=1;
					cnt[v]++;
					if(cnt[v]>=n){
						return 1;
					}
					q.push(v);
				}
			}
		}
	}
	return 0;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		add_edge(0,i,0);
	}
	for(int i=1;i<=m;i++){
		int opt;
		cin>>opt;
		if(opt==1){
			int a,b,c;//b<=a-c
			cin>>a>>b>>c;
			add_edge(a,b,-c);
		}
		else if(opt==2){
			int a,b,c;//a<=b+c
			cin>>a>>b>>c;
			add_edge(b,a,c);
		}
		else{
			int a,b;
			cin>>a>>b;//b<=a+0   &&   a<=b+0
			add_edge(a,b,0);
			add_edge(b,a,0);
		}
	}
	if(SPFA()){
		cout<<"No"<<endl;
	}
	else{
		cout<<"Yes"<<endl;
	}
	return 0;
}
posted @ 2025-12-09 22:09  Creativexz  阅读(4)  评论(0)    收藏  举报