• 关于差分约束系统的脑洞


    <未完成>

    差分约束是指形如 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).
    正图使结果满足约束后最大.
    反图使结果满足约束后最小(负值的时候最大,取负就变最小了).

  • 相关阅读:
    Javascript的this用法
    angularjs学习笔记--1.入门
    git的简单应用
    转:Netty服务器线程模型概览
    Netty 4.0 中文文档
    转:腾讯CKV海量分布式存储系统
    转Redis性能测试
    maven assemby 打包问题
    转发:TCP
    转:HBase Server启动过程
  • 原文地址:https://www.cnblogs.com/DragoonKiller/p/4295946.html
Copyright © 2020-2023  润新知