关于差分约束的一切
观前须知
笔者的博客主页
声明
本文使用 CC BY-NC-SA 4.0 许可。
本文为笔者在 OI 学习中的复习向学习笔记。
部分内容会比较简略。
如有好的习题会不断补充。
知识简介
差分约束解决这样一类问题:
给定一个 n 元一次不等式组,让你求出一组解/判定是否有解/算出某个数的最值/算出和的最值……
先从最简单的开始:
那么怎么做呢?
发现对于形如
对于一个这样的不等式组:
可以推出
联想一下,这个式子有什么意义呢?
来看这张图:
不难发现,有
那么我们可以把三个变量转换为三个点,对于每个约束两个变量关系的不等式,变为图上的一条边!
考虑最短路中的这个式子:
那么一个形如
就可以变成图上一条从
同理,一个形如
那么图就可以建出来了。
(如果涉及到
值得一提的一个性质:
一个这样的不等式组要不然无解,要不然有无数多组解。
因为只要有一组解
我们对于每个变量都加上一个相同的值变为
不难发现仍然是满足原不等式组的。
那么现在考虑什么情况下无解。
对于这样一个不等式组:
由第一个和第二个不等式相加可以推出
然而再和第三个不等式相加一下会变成
扩展一下,对于这样一个不等式组:
把这 n 个不等式全部相加会变成
那么可以发现,这在图上对应了一个负环。
所以当且仅当建出来的图上存在负环时无解。
判负环用 SPFA,对于不连通的图,添加一个超级源点,
从超级源点向所有点连权值为
若无负环,跑出来的 dis 数组即为一组解。
那么这道板子题,我们就解决了。
代码见:笔者的板子库。
但是还不够。
当我们固定源点的值后,我们就可以求出所有点与源点的差的最值。
求最小值,则跑最长路,求出一个
(这里最长路可以把图的边权全部取相反数,再跑最短路算出)
求最大值,则跑最短路,求出一个
如果要求所有变量和的最值呢?
例如令所有变量都为非负整数,求最小的变量和(见下面的习题)。
求最小值,我们跑最长路。
一个
建立超级源点,向各点连权值为 dis[0] = 0
),相当于让各个点的值都非负。
接下来从超级源点跑最长路,发现 dis 数组正好就是每个点能取的最小值,求和即为答案。
总结一下:
由于通常要跑 SPFA,所以差分约束的数据范围一般不会太大。
先确定要跑什么路,再建图。
重点在于建图的时候不要漏掉题目中的隐藏条件。
习题
YbtOj 1509 Intervals
对于
则题目中的条件可变为
注意隐藏条件:
建超级源点跑最长路,答案即为
细节:
由于有
Luogu P3275 【SCOI2011】 糖果
求最小变量和,跑最长路。
根据题意建图,对于
见超级源点跑最长路,答案为
这道题数据范围较大,差分约束会被 Hack 掉
然而笔者特判自环 + SPFA SLF-swap优化冲过去了
USACO 05DEC Layout G
令
按照题意建图,隐藏条件
建超级源点跑最短路,有负环则无解。
对于 1 号节点跑最短路,若与 n 号节点联通则
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!