差分约束系统整理

预备知识:最短路SPFA/Dijkstra等

一、定义

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

简单来说,只要问题能够被转化成一组  xi - xj <= k 的不等式,都可以用差分约束系统求解。(k的正负不重要)

二、原理

原理很简单,将 xi - xj <= k 移项得 xi + (-k) <= xj,与最短路中的松弛操作 d(u) + w(u, v) <= d(v) 非常类似,所以求解最大值/最小值的过程可以看作求解最短路中的松弛过程。

举个栗子:

给定不等式组

B - A <= a

C - A <= c

C - B <= b

求 C-A 的最大值,可以看出 max(C - A) = min(c, a + b),对应下图中A到C的最短路

观察上面例子中的不等式,都是 xi - xj <= k ,移项得 xi <= xj + k,我们记 v = xi, u = xj, k = w(xj, xi) = w(u, v),dis[v]=xi,dis[u] = xj,那么原式就变为:dis[u]+w(u,v)>=dis[v],对比最短路中的松弛操作:

if (dis[u] + w[u][v] < dis[v]) {
    dis[v] = dis[u] + w[u][v];
}

在最短路问题中经过松弛操作后,我们会得到 dis[v] <= dis[u] + w[u][v],和上式相同!因此我们可以通过判断最短路是否有解得出差分约束系统是否有解,通过求最短路/最长路得到差分约束系统的最大值/最小值。

具体表现为:

1、若要求xn - x1的最大值,就是求图中点x1到xn的最短路。经过松弛以后每条边都满足 dis[v] <= dis[u] + w[u][v],对每个不等式 xi - xj <= k 进行建边,把xj看成u,xi看作v,建立一条xj指向xi的有向边,边权为k。

2、若要求xn - x1的最小值,就是求点x1到nx的最长路。经过松弛以后每条边都有 dis[v] >= dis[u] + w[u][v],对于不等式 xi - xj <= k,先转换为 xj >= xi + (-k),此时可建立一条xi指向xj的有向边,边权为-k。

三、应用及步骤

3.1 建图

根据题目描述找出系统中的约束条件,根据需求建图。

差分约束系统有三种类型的题目:

1、求差的最大值,即最短路,建图方式可用上一部分中说到的第一种方法;

2、求差的最小值,即最长路,建图方式可用上一部分中的第二种方法;

3、判断是否有解,即是否有负环,此时用最长路和最短路建图方式都可以。

对于形如 xi - xj < k 的不等式,可以转化成 xi - xj <= k - 1 的形式。

对于 xi - xj == k,可添加 xi - xj >= k 和 xi - xj <= k 两个不等式。

3.2* 超级源点

有时候会遇到建出来的图是不连通的情况,这时候需要添加一个超级源点S0,从S0到任意顶点的距离都是0,这样的话能够保证构造的图是连通的且不引入负环,不会对最长路的结果造成影响。如果是最短路,可以S0到任意顶点都置为inf。

如果使用SPFA求最短路,可以不用附加顶点,初始的时候把所有顶点都加入队列, 并且将所有dis置0, 这就相当于加了一个不存在的附加顶点, 它与所有的顶点的直连长度都是0。

3.3 最短路/最长路

求最长路只需要初始将dis置于无穷小,使用 if(d[v] < d[u]+w(u,v)) 进行更新即可。

因为建好的图大部分情况下是有负边的,所以主要用SPFA,还可以判断负环。但是如果题目中保证了没有负边,最好用dijkstra+heap来写,因为时间稳定,不会被卡掉。这一点详见poj3159 https://blog.csdn.net/hcx11333/article/details/70942046

3.4 判断负环

用spfa即可,如果有顶点入队次数超过了顶点数,说明发生了存在死循环更新,此时结束算法即可。

四、题目

1、 求最大差值(最短路)

POJ3159 求最大差值,SPFA容易T,图中只有正边,所以可以用dijkstra。

https://blog.csdn.net/hcx11333/article/details/70942046

HDU3440 有点绕,求的是最大值还是最小值需要讨论。https://blog.csdn.net/hcx11333/article/details/81411852

2、求最小差值(最长路)

HDU2647 裸题,无负边,拓扑排序也能写。https://blog.csdn.net/hcx11333/article/details/81413171

HDU4109 裸题,建好图就行了。https://blog.csdn.net/hcx11333/article/details/81406760

ZOJ2770 求最小差值同时判断是否有解 https://blog.csdn.net/hcx11333/article/details/81392744

HDU1534 求最小差值同时判断是否有解 https://blog.csdn.net/hcx11333/article/details/81406751

POJ1201 区间约束型问题,建立起模型找出不等式关系就好了 https://blog.csdn.net/hcx11333/article/details/81414061

HDU1529 & POJ1275 差分约束+二分,有难度 https://blog.csdn.net/hcx11333/article/details/81396704

3、求是否有解(最长最短均可)

POJ2983 求是否有解,最长路最短路均可。https://blog.csdn.net/hcx11333/article/details/81481595

HDU1531 & POJ1364 求是否有解,建的图不一定连通,需要加超级源点。

https://blog.csdn.net/hcx11333/article/details/81396191

HDU3592 & POJ3169 最短路求最大差值,有负环就是无解,跑完后dis[n]==inf表示差值可以无限大。

https://blog.csdn.net/hcx11333/article/details/81413500

HDU4598 隐含的差分约束,讨论的情况有点多。https://blog.csdn.net/hcx11333/article/details/81484990

猜你喜欢

转载自blog.csdn.net/hcx11333/article/details/81389904