<未完成>
差分约束是指形如 x≤y+c 的不等式组构成的变量约束.
一般使用最短路 dist(v)≤dist(u)+w(u,v) 的特征求解.
最长路为 dist(v)≥dist(u)+w(u,v) .
直接给出约束条件求出它的一组解显然是没有任何问题的.
那么问题来了,求特定解怎么办?
和最大? 差最小?
我们来仔细分析.
先来看为什么差分约束能够用最短路找出解.
设有三个变量a,b,c.
以及三个式子
a+1≥c
a+2≥b
b+1≥c
把a点设为源点,即 dist(a)=0;
然后同通常最短路的做法,设 dist(b)=dist(c)=INF; (INF作infinity的缩写)
接着按照等式连边: (a,b,2) (b,c,1) (a,c,1);
首先,算法会松弛a到b这条边,即 a+2≥b 这个式子.
于是dist(b)=2;
我们来看一下算法到底做了什么.
一开始,a=0,b=INF.
a+2≥b并不成立.
第一次松弛使b=2,正好满足了不等式的条件.
不过,b=2并不是唯一的解.
b=1,b=0,b=-1….都是可行的.
可见一次松弛使得一个变量刚好满足所给定的约束条件.
算法继续.接下来松弛的是(b,c,1),dist(c)=3.
这与上边的差不多.
最后一次松弛是(a,c,1). dist(c)=1.
我们发现c的值被改变了,从3变成1.
这是为了满足约束条件 a+1≥c. 注意,我们先通过松弛修改满足了b+1>=c,然后再满足a+1>=c.
观察上边的过程,可以看到:
最短路算法总是使得点的值在满足约束的条件下是最大的.
这样证明:
设dist(x)是在算法结束以后x的节点值.
我们尝试把dist(x)增大.
但明显是不行的!
设修改了节点x的最后一次松弛操作是关于边(y,x,c)的.
而节点y的值已经是最大的了(否则我们可以递归地证明y最大,直到源点,源点的值是给定的).
边(y,x,c)的存在表明y+c≥x. 此时x=y+c.
很明显如果再增大x,y+c≥x将不再满足. 所以dist(x)是在满足约束条件下能够到达的最大解.
不过话说回来,在跑完算法以后减小dist(x)是可行的,特别是边权都为正时.
好了.接下来,换一种建图方式——我们用最长路.
对于每一条不等式x≤y+c,两边同时乘以-1: -x≥-y-c
我们用dist(x)来表示-x的值,dist(y)表示-y的值,从y向x连一条权为-c的边即可.
嗯…看起来没有任何问题对吧…..
对除源点外的每一个点赋值-INF并做最长路.可以仿照刚才的证明得出,
按照最长路所得到的权值是满足所有约束条件后权值最小的.
嗯看起来一点问题都没有……
那么现在问题来了.
对于不等式x≤y+c,移项: x-c≤y.
此时我们从x向y连一条权值为-c的边.
我们发现,这样构成的图和原图(未经处理的不等式构图)正好是相反的:
如果原图有边(y,x,c),那么这个图就有边(x,y,-c).
根据不等式的特征,我们应该做最长路.
嗯确实是最长路没有问题,因为我们都把边权取负了.
现在把它改成最短路,两边取负: -x+c≥-y,同样构图(x,y,c).
咦,这么做是原图的反图唉.
我们的问题是:
同一组不等式,以及同一组解法,不仅能构建出原图,还能构建出反图.
对反图跑最短路,以及对原图跑最短路, 有什么相同点和不同点?
首先是取值.
在原图中,x=dist(x). 反图中,-x=dist(x).
但是不论在原图还是反图,边权均为c.
这意味着什么呢?
设有点a,b,以及不等式a+1≥b.
原图连边(a,b,1),初始化dist(a)=0,dist(b)=INF.
算法结束后,dist(a)=0,dist(b)=1.
反图连边(b,a,1),初始化dist(a)=0,dist(b)=INF.
算法结束后,dist(a)=0,dist(b)=INF.
反图得出的结果实际上是-0+1≥-INF,是正确的.
我们尝试这样:
设有点a,b,以及不等式a-1≥b.
原图连边(a,b,-1),初始化dist(a)=0,ist(b)=0.
算法结束后,dist(a)=0,dist(b)=-1.
反图连边(b,a,-1),初始化dist(a)=dist(b)=0.
算法结束后,dist(a)=0,dist(b)=0.
反图无法算出正确的结果.
为什么呢?因为我们的算法总是从a开始进行的!
对于反图来说,根本都不连通,更别说更新节点值了.
这时候就需要超级源:每个点都能作为源点.
现在来谈论一下初始化问题.
设点a,b,以及a+1≥b.
超级源向a,b连权为0的边(即dist全初始化为0).
得到dist(a)=dist(b)=0.
这是符合要求的一组解.
反图呢,超级源进行同样操作.
得到dist(a)=dist(b)=0.
发现是一样的.
设点a,b,以及a-1≥b.
同样连变法,得dist(a)=0,dist(b)=-1.
反图呢?
dist(a)=-1,dist(b)=0.
别忘了反图是在对-x+c≤-y构图.
反图得出的结果实际上是 -(-1)-1≥0 成立.
但是两种结果并不一样.
正图: a=0,b=-1.
反图: a=1,b=0.
这就很值得思考了.
a,b都有着怎样的性质呢?
正图和反图的区别在于,连通性.
正图通过a更新b,反图不行.
反图通过b更新a,正图不行.
正图使得没有任何一个点的权值比初始值大.
反图使得没有任何一个点的权值比初始值的相反数小(存储的值总是小于等于0,取负以后总是大于等于0).
正图使结果满足约束后最大.
反图使结果满足约束后最小(负值的时候最大,取负就变最小了).