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;
}

浙公网安备 33010602011771号