差分约束系统

差分约束系统

山东省聊城第一中学 孙玉泰(Stockholm_Sun)

绪言

在我学习差分约束系统的时候,网络上的blog并不能很好的给我一个思路,这说明讲解这个系统绝非易事,那么接下来的讲解将较多的借鉴百度百科的资料,结合自己的思想来讲解,然后希望大家能坚持读完这些,因为这些都是我自认为比较通俗的,毕竟OI是一个比较艰辛的道路,大家一起努力吧。

预备定义
差分

又名差分函数或差分运算,差分的结果反映了离散量之间的一种变化,是研究离散数学的一种工具。它将原函数f(x) 映射到f(x+a)-f(x+b) 。差分运算,相应于微分运算,是微积分中重要的一个概念。总而言之,差分对应离散,微分对应连续。

SPFA算法或Bellman-Ford算法

这两个算法均为单源最短路算法,学习之前至少要会一个。下面给出SPFA的定义和上述算法之间的联系。
SPFA算法是求单源最短路径的一种算法,它还有一个重要的功能是判负环(在差分约束系统中会得以体现),在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。

偏移量

本讲中,对于一组有解的差分约束系统,假设解集为A,将元素中所有元素+δ,偏移量即为δ。此定义是临时定义,仅适用于本讲。

负环

对于图上的一个环来说,如果遍历一圈,总权值小于0,那么我们就称之为负环。

定义

如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统。差分约束系统是求解关于一组变量的特殊不等式组的方法。

实现思路

观察xj-xi<=bk,会发现它类似最短路中的三角不等式d[v]<=d[u]+w[u,v],即d[v]-d[u]<=w[u,v]。因此,以每个变量xi为结点,对于约束条件这里写图片描述,其意思为xj比xi至多多bk。连接一条边(i,j),边权为bk。
那么为什么是连接(i,j)呢?因为单源最短路是一个累加的过程,所以起始点要比终止点“小”bk个单位(实际上可以是bk<0时,xi比xj大)。这样一来,xi需要加上bk才是xj,所以要从i出发到j,建一条bk的边。这里讲的只是“至多型”,要求最短路。
同样的,我们如果要表述这里写图片描述时,即为这里写图片描述,就连接一条边(j,i),边权为-bk。
(据说是联系了网络流的思路)我们再增加一个超级源节点s,s与所有定点相连,边权均为0。
为什么要让边权为0呢?因为刚刚我们说了,(j,i)表示这里写图片描述,这样一来就可以让bj<=k,所以事实上边权为0完全可以改成任意的一个k,我们知道,如果这样的差分约束系统有解的话,就一定是有无穷种解,因为它们的偏移量有正无穷种情况,而这里的k就决定了差分约束系统的解集的偏移量,对于求最短路的“至多型”算法,这个k同时也是一个上界。
对这个图,以s为源点运行单源最短路算法,这里我们使用SPFA算法,最终{d[i]}即为一组可行解。
因此,求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题。

案例分析

下面来看看较为基础一些的案例:
找出未知量xi,i=1,2,…,5,满足下列8个差分约束条件(0节点已省略):
这里写图片描述
很容易就可以知道,该问题的一个解为x=(-5,-3,0,-1,-4),另一个解y=(0,2,5,4,1),这2个解是有联系的:y中的每个元素比x中相应的元素大5。
引理:设x=(x1,x2,…,xn)是差分约束系统Ax≤b的一个解,d为任意常数。则x+d=(x1+d,x2+d,…,xn+d)也是该系统Ax≤b的一个解。这里的5也就是我们所说的偏移量δ,但一般情况下,我们取0节点为0,以及0节点与其它节点连线的权值为0。
再一个就是对于相等时候的加边,需要加权值为0的双向边,这一点要注意。
然后为了检查对应不等式组是否对应解集,我们就只需要观察它是否存在负环,因为如果存在负环的话,每转一圈负环内所有元素的权值都会降低,在一个确定的偏移量下却不会是一个确定的数,所以就像A>B>C>A>B>C>……一样,是不成立的。

实质讨论

经过我和几个dalao的讨论,了解到这个求最短路(至多型)或者说最长路(至少型)的方法就是在模拟不等式合并的过程,即
a-b<=m···························不等式1
b-c<=n·····························不等式2
而最短(长)路的三角形原理在这里就是模拟了联立不等式组并将不等式1+不等式2的过程,即
a-c<=m+n·······················不等式3
这就是这个算法的实质,简直是数论与图论的完美结合,令人惊叹。

预备定义补充

在解释核心代码之前,我们先要熟悉一件事情。
对于我们要讲的SPFA算法,撇开它的两个优化法SLF和LLL不说,朴素的SPFA算法类似于BFS,它是广度优先的优化,而对于这个算法它的时间复杂度并不优秀,是O(N^2)的级别。所以这里我们用DFS版的SPFA,这也就是核心代码。

应用范围

经过lzh大佬的建议,在此强调一下差分约束系统的应用,比如说我们想要求出所有节点之间权值差值最大,那么我们就用“至多型”(<=),这个时候我们求最短路,原因是这样的:
a-b<=m···························不等式1
b-c<=n·····························不等式2
我们刚说了,差分约束的实质就是两个不等式的联立,这样我们就可以发现,根据同小取小原理,我们就求一个最短路。
反之,“至少型”用于求点权值差值最小,用最长路类比一下就好啦。
还有一个应用,就是求可行解,这种东西算出一个解来,然后枚举偏移量δ,只要有可行解,你想要几个解就有几个解,因为刚才说了,它的解集数是无穷个或者0个。

代码实现

建边的方法和初始化的东西就不讲了,初始化就是把d数组(distance)升为MAX即可,然后开始点的d初始化为0。
接下来重点看看算法,这个代码的功能是求在给定条件下,是否存在解。也就是判断负环,如果一个节点在被更新时这个节点在更新队列中,说明它存在负环,因为在0节点权值为0时,如果节点X要更新,X的权值必定是比原来的X的非正权值小,即更新后X的权值必定为负数,那么它就是一个负环,所以不合题意,直接输出NO。

int dfs(int x)
{
    b[x]=1;
    for(int i=hd[x];i;i=nxt[i])//遍历x相连的点
    {
        if(d[x]+v[i]<d[y[i]])//更新节点
        {
            d[y[i]]=d[x]+v[i];
            if(!b[y[i]])//如果当前没有发现成负环就继续
            {
                if(!dfs(y[i]))
                return 0;
            }
            else//反之错误
            return 0;
        }
    }
    b[x]=0;//解除标记
    return 1;
}
结束语

差分约束系统,在我看来是一个数字与图论的完美结合,有时候数学需要图论来作工具才可相得益彰,琴瑟和鸣。
版权所有,Stockholm_Sun
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值