差分约束系统
来源:互联网 发布:linux命令行退出全屏 编辑:程序博客网 时间:2024/06/05 20:01
差分约束系统是线性规划问题的一个特例。k行n列的线性规划矩阵
单源最短路问题
这个问题可以从另一个角度来理解:给每个顶点
1.
2.
约束图
移项得
发现它和最短路问题中的三角不等式是一致的:
由此,我们建图如下,得到差分约束系统的一组可行解或判其无解:
添加额外的源点
这样的一个图称为约束图。
无解
为什么存在负圈意味着差分约束系统无解呢?我们来证明一下。
设
全部加起来,有
这是不科学的。证毕。
转化
解的特性
定理1:如果
证明略。
定理2:由约束图得到的可行解满足
证明略。
定理3:由约束图得到的可行解与其他满足
假设另有一组满足
UPDATE 2016.9.10
和WZH学长讨论有没有更直观的证法,受到启发,如下:
x、y还是和上面一样。从
和
分别全部相加,得
代入
证毕。
定理4:由约束图得到的可行解最小化
由定理1,我们可以“平移”解向量。这个变换不改变各个变量的相对大小。假设另有一组可行解
如果我们要最小化
把最短路改为最长路即可。
怎么求最长路呢?一种方法是把所有边权取反,用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;}
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 【差分约束系统】
- 差分约束系统
- 差分约束系统
- 差分约束系统
- ##差分约束系统##
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- 差分约束系统
- Linux的SSH原理以及Putty配置sshkey
- 敏捷项目管理--流程管理
- 需要关注的技术网站 & 不错的个人博客站点
- 移动
- Linux下的环境变量
- 差分约束系统
- 从安卓的Looper到iOS的RunLoop
- VS2015,matlab2016混合编程
- python中的python from __future__ import division
- C++编程入门系列之六(算法的基本控制结构之选择结构)
- IE8解决new Date("2016-9-5")返回NaN问题
- C#控制台基础 将char类型数组转换为string字符串 new string()
- .NET 环境中使用RabbitMQ
- unity组件的添加和删除