题解 P1993 【小 K 的农场】

· · 题解

差分约束

前置知识: P5960 【模板】差分约束算法

这题转化为差分约束比较简单。

题面给的 1 就相当于 a-b\ge c,两边同时乘 -1 得 b-a\le-c ,变成了差分约束的形式。

$3$ 就相当于 $a=b$,也就是 $a-b=0$ ,转化成不等式就是 $a-b\le 0$ 且 $a-b\ge 0$,后面的不等式可以用 $1$ 的方法,变成 $b-a\le 0$。 这样,都转化成了差分约束的形式,套板子即可。 代码(貌似大常数,需要吸氧): ```cpp #include<iostream> #include<queue> using namespace std; const int N=5005; struct edge { int to,nxt,v; }e[4*N]; int n,m,cnt; int head[N],dis[N],tot[N],v[N]; void add(int u,int v,int w) { cnt++; e[cnt].to=v; e[cnt].v=w; e[cnt].nxt=head[u]; head[u]=cnt; } bool spfa() { queue<int> q; for(int i=1;i<=n;i++) dis[i]=2e9; q.push(0); v[0]=1; while(!q.empty()) { int now=q.front();q.pop(); v[now]=0; for(int i=head[now];i;i=e[i].nxt) { if(dis[e[i].to]>dis[now]+e[i].v) { dis[e[i].to]=dis[now]+e[i].v; if(!v[e[i].to]) { v[e[i].to]=1; tot[e[i].to]++; if(tot[e[i].to]==n) return 0; q.push(e[i].to); } } } } return 1; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) add(0,i,0); for(int i=1;i<=m;i++) { int op,a,b,c; cin>>op>>a>>b; if(op==1) { cin>>c; add(a,b,-c); } if(op==2) { cin>>c; add(b,a,c); } if(op==3) { add(a,b,0); add(b,a,0); } } cout<<(spfa()?"Yes":"No"); return 0; } ```