这篇文章上次修改于 243 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
ACM程序课算法笔记11——差分约束
差分约束方程组
差分约束指的是一种多个元素之间差的限制,而求某两个值的最大差。
例如求:
x1 - x0 <= 2——①
x2 - x0 <= 7——②
x3 - x0 <= 8——③
x2 - x1 <= 3——④
x3 - x2 <= 2——⑤
求x3-x0的最大值。
对于这个式子,我们可以通过很简单的联立来获得关系式
x3 - x0 <= 8——③
(x3 - x2) + (x2 - x0) <= 7 + 2——②⑤
(x3 - x2) + (x2 - x1) + (x1 - x0) <= 2 + 3 + 2——①④⑤
最终三式子得到 8 9 7三个值
得到x3 - x0 <= 7
问题转化一(<= & <)
通过上式的联立我们可以很快发现,这三个值的获取,就相当于从x0直接走到x3,从x0走过x2再到x3等等。这和有向图是几乎一样的。
无异于 0->1 边权2,0->2 边权7,0->3 边权8,1->2 边权3,2->3 边权2
当我要求x3的最大值时,也就是求0到3的最短路径。
注意为什么是最短路径,当你求的是最大值的时候,你得到的路径权值是约束条件,如同上面的8 9 7一样,是小于等于它们,所以我们要取最小的,也就是最短路径。
问题转化二(>= & >)
上面是最好理解的<=
符号,现在当遇到>=
时,也就两边取负变号,也就变成了上面一样的方式,只不过边权取负,方向相反。
或者是换一个理解方式,所有都为>=
,此时就需要转换一下,所有的值都变成大于等于,最后联立得到的多个约束值也是大于等于,此时就是找到多个约束值的最大值,最后求的也是最小值。就变成了最大路径问题。
注意:Dij不能用于计算最大路径问题,原因是贪心思路的时候,dij的最短路保证最短路径的那个点已经是答案了,但对于最长路,最长路径的点也不一定是答案,破坏了贪心的思路。
问题转化三(=)
当遇到=
的要求时,实际上就是两个符号的组合起来,=
等价于>=
&<=
,同时满足两个条件,这也就是一个双向的边,不过要注意权值正负不同。
例题:整数区间
内容:
给定 n 个整数闭区间 [ai, bi] 和 n 个整数 c1, …, cn。
读取区间数、它们的端点和整数 c1, …, cn,
计算整数集 Z 的最小大小,该数集满足和区间 [ai , bi]至少有 ci 个公共元素( i = 1, 2, …, n )
题解:
这是一道很隐藏的差分约束,其特点难以发现。我们不妨记录a[i]代表前i个数字,区间选择了a[i]个数,那么对于区间[left, right]内至少要选择c个元素也就是
a[right] - a[left - 1] >= c
同时我们还有个差分条件也就是
1 >= a[x] - a[x - 1] >= 0
根据以上约束条件做出边即可
又水了一篇博客