[洛谷P1993]小K的农场

题目大意:有n个数和一些条件。条件有三种。

1.$a-bgeq c$;2.$a-bleq c$;3.$a=b$。

问你能否使得这些数满足所有条件。

解题思路:差分约束系统。

对于$a-bleq c$这样的不等式,我们将b->a连一条边权为c的有向边。

对于$a=b$,我们在a、b间连一条边权为0的无向边。

最后建立一个节点0,从它向所有节点连一条边权为0的有向边,然后从0开始跑SPFA判负环即可。

如果最后跑出来有负环,则无解,否则一定有解。

对于第1种条件,可以把它转变为$b-aleq -c$,然后按上述方法建图即可。

判负环时用dfs好像会更快一点。

C++ Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
int n,m,head[10005],dis[10005];
bool vis[10005];
struct edge{
	int to,dis,nxt;
}e[1000005];
inline int readint(){
	char c=getchar();
	for(;!isdigit(c);c=getchar());
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return d;
}
void dfs(int now){
	vis[now]=true;
	for(int i=head[now];i!=-1;i=e[i].nxt){
		if(dis[e[i].to]>dis[now]+e[i].dis){
			dis[e[i].to]=dis[now]+e[i].dis;
			if(vis[e[i].to]){
				puts("No");
				exit(0);
			}
			dfs(e[i].to);
		}
	}
	vis[now]=false;
}
int main(){
	int cnt=0;
	memset(head,-1,sizeof head);
	n=readint(),m=readint();
	for(;m--;){
	int opt=readint(),a=readint(),b=readint();
		if(opt==1){
			int c=readint();
			e[++cnt]=(edge){b,-c,head[a]};
			head[a]=cnt;
		}else
		if(opt==2){
			int c=readint();
			e[++cnt]=(edge){a,c,head[b]};
			head[b]=cnt;
		}else{
			e[++cnt]=(edge){a,0,head[b]};
			head[b]=cnt;
			e[++cnt]=(edge){b,0,head[a]};
			head[a]=cnt;
		}
	}
	for(int i=1;i<=n;++i){
		e[++cnt]=(edge){i,0,head[0]};
		head[0]=cnt;
	}
	memset(vis,0,sizeof vis);
	memset(dis,0x3f,sizeof dis);
	dis[0]=0;
	dfs(0);
	puts("Yes");
	return 0;
}
原文地址:https://www.cnblogs.com/Mrsrz/p/7808805.html