差分约束系统
2016-09-05 13:57
162 查看
差分约束系统是线性规划问题的一个特例。k行n列的线性规划矩阵A的每一行包含一个1和一个-1,其余均为0。也就是说,每个约束条件都形如
xj−xi≤bk
1. δ(s,v)≤δ(s,u)+w(u,v),(u,v)∈E
2. 存在(u,v)∈E,使得δ(s,v)=δ(s,u)+w(u,v)
xj≤bk+xi
发现它和最短路问题中的三角不等式是一致的:
δ(s,v)≤δ(s,u)+w(u,v),(u,v)∈E
由此,我们建图如下,得到差分约束系统的一组可行解或判其无解:
添加额外的源点v0,从v0向每个xi连一条有向边,边权为0。对于每个不等式xj−xi≤bk,连有向边(vi,vj),w(vi,vj)=bk。求以v0为源点的单源最短路,如果存在负圈,则无解;否则,xi=δ(s,vi),1≤i≤n是差分约束系统的一组可行解。
这样的一个图称为约束图。
设<v1,v2,...,vm>是约束图中的一个负环,v1=vm。相应地,差分约束系统中有不等式
x2−x1≤w(v1,v2)x3−x2≤w(v2,v3)...vm−vm−1≤w(vm−1,vm)
全部加起来,有
0≤一个负数
这是不科学的。证毕。
证明略。
定理2:由约束图得到的可行解满足xi≤0。
证明略。
定理3:由约束图得到的可行解与其他满足xi≤0的可行解相比,最大化Σni=1xi。
假设另有一组满足yi≤0的可行解(y0,y1,y2,...,yn),为了统一起见,同样附加一个y0=0。考察源点到任意一点,不妨设其为vn,最短路径为<v0,v1,v2,...,vn>。x0≥y0。假设xi≥yi成立,那么xi+1=xi+w(vi,vi+1)≥yi+w(vi,vi+1)≥yi+1。第一个等号是根据最短路的性质。由数学归纳法,对于所有xi,均有xi≥yi成立,因而最大化了Σni=1xi。
UPDATE 2016.9.10
和WZH学长讨论有没有更直观的证法,受到启发,如下:
x、y还是和上面一样。从v0到vn,有
xn−xn−1=w(vn−1,vn)xn−1−xn−2=w(vn−2,vn−1)...x1−x0=w(v0,v1)
和
yn−yn−1≤w(vn−1,vn)yn−1−yn−2≤w(vn−2,vn−1)...y1−y0≤w(v0,v1)
分别全部相加,得
xn−x0=Σwyn−y0≤Σw
代入x0=y0=0,得
xn≥yn
证毕。
定理4:由约束图得到的可行解最小化max{xi}−min{xi}。
由定理1,我们可以“平移”解向量。这个变换不改变各个变量的相对大小。假设另有一组可行解(y1,y2,...,yn),将它平移,使得max{yi}=max{xi}。由定理3的证明,min{xi}≥min{yi},故max{xi}−min{xi}≤max{yi}−min{yi}。
如果我们要最小化Σni=1xi,最大化max{xi}−min{xi},该怎么做呢?
把最短路改为最长路即可。
怎么求最长路呢?一种方法是把所有边权取反,用SPFA求最短路。另一种方法是直接修改SPFA松弛的条件。注意这里的最长路与无权简单最长路的区别,所以它不是NP完全问题。
一开始TLE,上网搜索,得知这道题有两个坑:
1. 有一组数据是一条很长的链。不知道除了面向数据还有什么解决方法呢?
2. 有一组数据存在很大的负环。虽然这组数据存在负的自环,可以直接判掉……
关于负环的判定,我参考了lydrainbowcat的方法:记录最短路径的长度。
不良心的出题人。
xj−xi≤bk
单源最短路问题
这个问题可以从另一个角度来理解:给每个顶点v分配一个顶标δ(s,v),满足:1. δ(s,v)≤δ(s,u)+w(u,v),(u,v)∈E
2. 存在(u,v)∈E,使得δ(s,v)=δ(s,u)+w(u,v)
约束图
移项得xj≤bk+xi
发现它和最短路问题中的三角不等式是一致的:
δ(s,v)≤δ(s,u)+w(u,v),(u,v)∈E
由此,我们建图如下,得到差分约束系统的一组可行解或判其无解:
添加额外的源点v0,从v0向每个xi连一条有向边,边权为0。对于每个不等式xj−xi≤bk,连有向边(vi,vj),w(vi,vj)=bk。求以v0为源点的单源最短路,如果存在负圈,则无解;否则,xi=δ(s,vi),1≤i≤n是差分约束系统的一组可行解。
这样的一个图称为约束图。
无解
为什么存在负圈意味着差分约束系统无解呢?我们来证明一下。设<v1,v2,...,vm>是约束图中的一个负环,v1=vm。相应地,差分约束系统中有不等式
x2−x1≤w(v1,v2)x3−x2≤w(v2,v3)...vm−vm−1≤w(vm−1,vm)
全部加起来,有
0≤一个负数
这是不科学的。证毕。
转化
xj−xi≥bk<=>xi−xj≤−bkxj−xi<bk<=>xj−xi≤bk−1xj−xi>bk<=>xi−xj≤−bk+1xi=xj<=>xi≤xj and xj≤xixi≤bk<=>xi−0≤bk解的特性
定理1:如果(x1,x2,...,xn)是一组可行解,那么(x1+d,x2+d,...,xn+d)也是一组可行解。证明略。
定理2:由约束图得到的可行解满足xi≤0。
证明略。
定理3:由约束图得到的可行解与其他满足xi≤0的可行解相比,最大化Σni=1xi。
假设另有一组满足yi≤0的可行解(y0,y1,y2,...,yn),为了统一起见,同样附加一个y0=0。考察源点到任意一点,不妨设其为vn,最短路径为<v0,v1,v2,...,vn>。x0≥y0。假设xi≥yi成立,那么xi+1=xi+w(vi,vi+1)≥yi+w(vi,vi+1)≥yi+1。第一个等号是根据最短路的性质。由数学归纳法,对于所有xi,均有xi≥yi成立,因而最大化了Σni=1xi。
UPDATE 2016.9.10
和WZH学长讨论有没有更直观的证法,受到启发,如下:
x、y还是和上面一样。从v0到vn,有
xn−xn−1=w(vn−1,vn)xn−1−xn−2=w(vn−2,vn−1)...x1−x0=w(v0,v1)
和
yn−yn−1≤w(vn−1,vn)yn−1−yn−2≤w(vn−2,vn−1)...y1−y0≤w(v0,v1)
分别全部相加,得
xn−x0=Σwyn−y0≤Σw
代入x0=y0=0,得
xn≥yn
证毕。
定理4:由约束图得到的可行解最小化max{xi}−min{xi}。
由定理1,我们可以“平移”解向量。这个变换不改变各个变量的相对大小。假设另有一组可行解(y1,y2,...,yn),将它平移,使得max{yi}=max{xi}。由定理3的证明,min{xi}≥min{yi},故max{xi}−min{xi}≤max{yi}−min{yi}。
如果我们要最小化Σni=1xi,最大化max{xi}−min{xi},该怎么做呢?
把最短路改为最长路即可。
怎么求最长路呢?一种方法是把所有边权取反,用SPFA求最短路。另一种方法是直接修改SPFA松弛的条件。注意这里的最长路与无权简单最长路的区别,所以它不是NP完全问题。
例题
Bzoj 2330 [SCOI2011]糖果一开始TLE,上网搜索,得知这道题有两个坑:
1. 有一组数据是一条很长的链。不知道除了面向数据还有什么解决方法呢?
2. 有一组数据存在很大的负环。虽然这组数据存在负的自环,可以直接判掉……
关于负环的判定,我参考了lydrainbowcat的方法:记录最短路径的长度。
不良心的出题人。
#include <cstdio> #include <queue> #include <cctype> #define NO_SOL() {puts("-1"); return 0;} using namespace std; typedef long long ll; const int MAX_N = 100000, MAX_K = 100000; int e_ptr = 1, n, k, head[MAX_N+1], d[MAX_N+1]; ll dis[MAX_N+1]; bool inq[MAX_N+1]; struct Edge { int v, next; ll w; } E[MAX_K*2+1]; inline void add(int u, int v, ll w) { E[e_ptr] = (Edge){v, head[u], w}; head[u] = e_ptr++; } bool SPFA() { queue<int> Q; for (int i = 1; i <= n; ++i) { inq[i] = true; dis[i] = -1; Q.push(i); } int u; while (!Q.empty()) { u = Q.front(); Q.pop(); inq[u] = false; for (int i = head[u]; i; i = E[i].next) { int v = E[i].v; ll upd = dis[u] + E[i].w; if (dis[v] > upd) { dis[v] = upd; d[v] = d[u] + 1; if (d[v] > n) return false; if (!inq[v]) { inq[v] = true; Q.push(v); } } } } return true; } template<typename T> inline void read(T& x) { x = 0; char c = getchar(); while (!isdigit(c)) c = getchar(); while (isdigit(c)) { x = x*10 + c - '0'; c = getchar(); } } int main() { read(n); read(k); int x, a, b; for (int i = 0; i < k; ++i) { read(x); read(a); read(b); switch (x) { case 1: // a = b add(a, b, 0); add(b, a, 0); break; case 2: // a < b if (a == b) NO_SOL(); add(a, b, -1); break; case 3: // a >= b add(b, a, 0); break; case 4: // a > b if (a == b) NO_SOL(); add(b, a, -1); break; case 5: // a <= b add(a, b, 0); } } // 求最长路,边权取负后求最短路 if (!SPFA()) NO_SOL(); ll ans = 0; for (int i = 1; i <= n; ++i) ans -= dis[i]; printf("%lld\n", ans); return 0; }
相关文章推荐
- 差分约束系统--简单?不简单?
- Poj 1201 (差分约束系统)
- POJ 1364 King(差分约束系统)
- poj1716 差分约束系统
- POJ 3169 Layout(差分约束系统)
- ZOJ 1508 poj 1201 Intervals 差分约束系统
- POJ 1364 King 差分约束系统
- POJ 1201 Intervals (差分约束系统)
- 学习笔记----差分约束系统初步 POJ 2983 Is the Information Reliable?
- UVa 515 King(差分约束系统)
- 2330: [SCOI2011]糖果 (差分约束系统)
- 差分约束系统详解(hdu1531 King为例)
- POJ 3169 Layout (差分约束系统 + Bellman-ford算法)
- 差分约束系统【模板】
- UVA 11478 Halum(差分约束系统+Bellman-Ford)
- 对于差分约束系统的一些理解
- 差分约束系统总结
- ZOJ2770 Burn the Linked Camp(差分约束系统)
- zoj1420Cashier Employment【差分约束系统论文题】
- usaco布局(差分约束系统的应用)