预备知识:最短路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