差分约束
引入
考虑单源最短路的一个性质:
在有向图中,若存在边 \(u\to v\),边权为 \(w\),则 \(dis_u+w\ge dis_v\)。
正确性是显然的,因为如果反之 \({dis}_u+w<dis_v\),我们就可以令 \({dis}_v\gets dis_u+w\),原先的就不是最短路了,与题设矛盾。
那么怎么使用这个性质呢?
正文
当题目中出现形如
\(m\) 个限制条件,\(n\) 个变量 \(x_i\),每个限制条件形如:\(x_a-x_b\le y\)。
时,就可以建图跑最短路。\(x_a-x_b\le y\implies x_b+y\ge x_a\),即 \(b\) 向 \(a\) 连边权为 \(y\) 的边。
例题
Luogu P5960 【模板】差分约束
直接连边跑最短路即可。但观察到无法快速确定一个源点,使得从它开始可以遍历到每个点。
技巧 \(1\):可以建立超级源点 \(0\),让 \(0\) 向每一个点连边。如果被卡可以 random_shuffle()
一下 \(0\) 的出边。
例题:Luogu P1993 小 K 的农场
同理,需要判负环。直接上队列优化 Bellman-Ford。
Luogu P3275 [SCOI2011] 糖果
依然考虑差分约束。
先使用技巧 \(1\),超级源点连所有点,边权为 \(1\),这样满足每个小朋友都可以分到糖果。
注意到边权只为 \(\{0,-1\}\),跑最短路可能使小朋友倒贴糖果 \(dis\) 为负。
当然,可以一负到底,将上面连超级源点的边权改成 \(-1\),然后输出 \(-dis(i)\) 即可。
技巧 \(2\):变正权边。
可以将边权取相反数,跑最长路。注意该技巧没有本质优化,不可以实现“变正权边跑 dijkstra”之类的操作。
这个技巧唯一的用处就是思路更顺。注意即使是“最长路”求出的未知数和照样最小,最长路只是保证约束条件。
但本题可以把队列优化 Bellman-Ford 卡爆!怎么办?
技巧 \(3\):配合 Tarjan 缩点。
以下题解使用了 技巧 \(2\),当然不用也可以做。
先缩点,每个 SCC 内部如果出现了一条 \(u\) 到 \(v\) 的边权为 \(1\),根据 SCC 的定义,一定还存在一条 \(v\) 到 \(u\) 的路径,由于边权 \(\ge 0\),所以一定会出现一个正权环,则这个差分约束系统无解。
否则的话,发现 SCC 内部变量取值一定是相同的,那么问题变成了一个 DAG 上最长路,拓扑排序即可。
——来自该题题解