关于差分约束的一切

观前须知

笔者的博客主页

声明

本文使用 CC BY-NC-SA 4.0 许可

本文为笔者在 OI 学习中的复习向学习笔记。
部分内容会比较简略。
如有好的习题会不断补充。

知识简介

差分约束解决这样一类问题:
给定一个 n 元一次不等式组,让你求出一组解/判定是否有解/算出某个数的最值/算出和的最值……
先从最简单的开始:

P5960 【模板】差分约束

那么怎么做呢?
发现对于形如 \(x_i - x_j \le c\) 的一个不等式可变形为 \(x_i \le x_j + c\)
对于一个这样的不等式组:

\[\begin{cases} x_1 \le x_2 + c_1 \\ x_2 \le x_3 + c_2 \\ x_1 \le x_3 + c_3 \\ \end{cases} \]

可以推出 \(x_1 \le x_3 + \min(c_1 + c_2,c_3)\)
联想一下,这个式子有什么意义呢?

来看这张图:
三角不等式

不难发现,有 \(x_1 \le x_3 + \operatorname{Dis}(x_1,x_3)\)
那么我们可以把三个变量转换为三个点,对于每个约束两个变量关系的不等式,变为图上的一条边!
考虑最短路中的这个式子: \(dis_v \le dis_u + w\)
那么一个形如 \(x_i - x_j \le c\)\(x_i \le x_j + c\) 的式子,
就可以变成图上一条从 \(j\) 指向 \(i\),权值为 \(c\) 的边!
同理,一个形如 \(x_i - x_j \ge c\) 的式子, 可以变为一条从 \(i\) 指向 \(j\),权值为 \(-c\) 的边。
那么图就可以建出来了。
(如果涉及到 \(x_i - x_j < c\) 的式子,可以考虑变为 \(x_i - x_j <= c - 1\) 处理)

值得一提的一个性质
一个这样的不等式组要不然无解,要不然有无数多组解
因为只要有一组解 \(\{ x_1,x_2,x_3,\cdots,x_n\}\)
我们对于每个变量都加上一个相同的值变为 \(\{ x_1+d,x_2+d,x_3+d,\cdots,x_n+d\}\)
不难发现仍然是满足原不等式组的。
那么现在考虑什么情况下无解。

对于这样一个不等式组:

\[\begin{cases} x_1 - x_2 \le 3\\ x_2 - x_3 \le -5\\ x_3 - x_1 \le 1\\ \end{cases} \]

由第一个和第二个不等式相加可以推出 \(x_1 - x_3 \le -2\)
然而再和第三个不等式相加一下会变成 \(0 \le -1\),显然无解。
扩展一下,对于这样一个不等式组:

\[\begin{cases} x_1 - x_2 \le c_1\\ x_2 - x_3 \le c_2\\ \vdots\\ x_{n-1} - x_n \le c_{n-1}\\ x_n - x_1 \le c_n \end{cases} \]

把这 n 个不等式全部相加会变成 \(0 \le \sum c_i\),当且仅当 \(\sum c_i < 0\)时无解。
那么可以发现,这在图上对应了一个负环
所以当且仅当建出来的图上存在负环时无解
判负环用 SPFA,对于不连通的图,添加一个超级源点
从超级源点向所有点连权值为 \(0\) 的边,然后从超级源点跑最短路即可。
若无负环,跑出来的 dis 数组即为一组解。

那么这道板子题,我们就解决了。
代码见:笔者的板子库

但是还不够。
当我们固定源点的值后,我们就可以求出所有点与源点的差的最值
最小值,则跑最长路,求出一个 \(dis_u \ge x\) 的下界。
(这里最长路可以把图的边权全部取相反数,再跑最短路算出)
最大值,则跑最短路,求出一个 \(dis_u \le x\) 的上界。

如果要求所有变量和的最值呢?
例如令所有变量都为非负整数,求最小的变量和(见下面的习题)。
求最小值,我们跑最长路。
一个 \(x_i \ge x_j + c\) 的式子,变为图上一条从 \(j\) 连向 \(i\),权值为 \(c\) 的边(与小于号的形式类似)
建立超级源点,向各点连权值为 \(0\) 的边,并钦定该源点的值为 \(0\) (在代码里体现为dis[0] = 0),相当于让各个点的值都非负。
接下来从超级源点跑最长路,发现 dis 数组正好就是每个点能取的最小值,求和即为答案。

总结一下
由于通常要跑 SPFA,所以差分约束的数据范围一般不会太大。
先确定要跑什么路,再建图。
重点在于建图的时候不要漏掉题目中的隐藏条件

习题

YbtOj 1509 Intervals

对于 \(0\)\(5\times 10^4\) 的每个值建一个变量 \(s_i\) 表示前缀和。
则题目中的条件可变为 \(s_b - s_{a-1} \ge c\)
注意隐藏条件:\(s_i \le s_{i+1}\) 以及 \(s_{i+1} - s_i \le 1\)
建超级源点跑最长路,答案即为 \(s_{5\times 10^4}\)

细节:
由于有 \(s_{-1}\) 存在,对于所有节点编号加一再建图。

Luogu P3275 【SCOI2011】 糖果

求最小变量和,跑最长路。
根据题意建图,对于 \(x_a < x_b\) 的条件变为 \(x_a \le x_b - 1\)
见超级源点跑最长路,答案为 \(\sum dis_i\)

这道题数据范围较大,差分约束会被 Hack 掉
然而笔者特判自环 + SPFA SLF-swap优化冲过去了

USACO 05DEC Layout G

\(d_i\) 表示前缀距离。
按照题意建图,隐藏条件 \(d_i - d_{i+1} \le 0\)
建超级源点跑最短路,有负环则无解。
对于 1 号节点跑最短路,若与 n 号节点联通则 \(dis_n\) 即为答案,否则两点间距离可以任意大。

posted @ 2024-04-09 12:33  Sugar_Cube  阅读(339)  评论(1编辑  收藏  举报