概括
如果一个系统由 n 个变量和 m 个约束条件组成,形成 m 个形如 ai - aj ≤ k 的不等式(i , j ∈ [1,n], k 为常数),则称其为差分约束
求不等式的可行解
源点需要满足的条件: 从源点出发,一定可以走到所有的边
否则 用单源最短路做的话 有一条边走不到 则该边对应的不等式就无法满足
-
把每个x[i] ≤ x[j] + C[k]不等式转化为一条从 x[j] 走到 x[i] 长度为 C[k] 的边
-
然后在这个图上找一个超级源点,使得该源点一定可以遍历到所有边
-
从源点求一遍单源最短路
3.1假如存在负环x[2] ≤ x[1] + c[1]
…
x[k] ≤ x[k-1] + c[k-1]
x[1] ≤ x[k] + c[k]
对第一个不等式用后面的不等式一直做松弛
x[2] ≤ x[1]+c[1]
≤ x[k] + c[k] + c[1]
≤ x[k-1] + c[k-1] + c[k] + c[1]
…
≤ x[2] + c[2] +…+ c[k-1] + c[k] + c[1]
≤ x[2] + (小于零的Σc[i])
x[2] < x[2]矛盾
得出结论:不等式无解 即存在负环
4.求完单源最短路之后
存在负环 => 不等式无解
没有负环 => 求完之后一定是满足这个不等式的 <=> 即一个可行解
求最大值或最小值
结论 : 如果求的是最小值,则应该求最长路,如果求的是最大值,则应该求最短路
问题 : 如何转化 x[i] ≤ c (其中 c 是一个常数) 这类的不等式
方法 : 建立一个超级源点, 0 号点 x[0] ,然后建立 0→i 长度是 c 的边即可
x[i] ≤ c <=> x[i] ≤ x[0] + c = 0 + c
以求 x[i] 的最大值为例:所有从 x[i] 出发,构成的不等式链
x[i] ≤ x[j] + c[1] ≤ x[k] + c[2] + c[1] ≤⋅⋅⋅≤ x[0] + c[1] + c[2] +⋅⋅⋅+ c[m] (x0=0)
所计算出的上界,最终 x[i] 的最大值 = 所有上界的最小值
那么求x[i]最大值
求所有上界的最小值
求所有从 0→i 的路径和的最小值
最短路求 dist[i]
例题
题目概括
幼儿园里有 N 个小朋友,老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。
但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候, 老师需要满足小朋友们的 K 个要求。
幼儿园的糖果总是有限的,老师想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入
输入的第一行是两个整数 N,K。
接下来 K 行,表示分配糖果时需要满足的关系,每行 3 个数字 X,A,B。
如果 X=1.表示第 A 个小朋友分到的糖果必须和第 B 个小朋友分到的糖果一样多。
如果 X=2,表示第 A 个小朋友分到的糖果必须少于第 B 个小朋友分到的糖果。
如果 X=3,表示第 A 个小朋友分到的糖果必须不少于第 B 个小朋友分到的糖果。
如果 X=4,表示第 A 个小朋友分到的糖果必须多于第 B 个小朋友分到的糖果。
如果 X=5,表示第 A 个小朋友分到的糖果必须不多于第 B 个小朋友分到的糖果。
小朋友编号从 1 到 N。
输出
输出一行,表示老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出 −1。
由题我们可以转换成不等式
- A = B <=> A≥B B≥A
- A < B <=> B≥A+1
- A≥B <=> A≥B
- A > B <=> A≥B+1
- B≥A <=> B≥A
每个人都能够分到糖果所以可以得到 x ≥ 1
x ≥ x0 + 1 可以设源点 x0 = 0
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;