『笔记』差分约束系统
定义
是个啥???
如果一个系统由 \(n\) 个变量和 \(m\) 个约束条件组成,形成 \(m\) 个形如 \(x_i - y_i \leq k\) 的不等式( \(i,j \in [ 1 , n ]\) ,\(k\) 为常数),则称其为差分约束系统( \(system\) \(of\) \(difference\) \(constraints\))。
亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。
说句人话就是:
差分约束系统就是给出一些形如 \(x - y \leq b\) 不等式的约束,问你是否有满足问题的解,或者求最小,最大解。
实现
这类问题的 \(NB\) 之处就是可以转化为图论的最短路问题。
瞎搞
令 \(a_k = w(j,i)\) ,则有
令 \(i = to\) , \(j = from\) , \(x = dis\) ,则有
\(SPFA\) 中的一个松弛操作:
if(dis[to] > dis[from] + w(from,to))
dis[to] = dis[from] + w(from,to)
就是使 \(dis_{to} \leq dis_{from} + w(from,to)\) 。
So~ 就可以针对每个 \(i\) 和 \(j\) 节点,建一条权值为 \(a_k\) 的有向边,然后连图,求 \(x_{n} - x_1\) 的最大值就是求节点 \(1 \to n\) 的最短路。
三角形不等式
有 \(x_i ? x_j \leq k\) 的一堆不等式。
转化为单源最短路中三角不等式 \(dis_i \leq dis_j + k\) 的形式,从 \(j\) 向 \(i\) 连一条权值为 \(k\) 的单向边。
建立超级源点,与各点距离为 \(0\),跑最短路。
若有负环则无解,否则最短路即为一组合法解。
合法解同加 \(\Delta\) 仍为合法解。
就是这么个玩意
然后
\(B - A \leq c\) ①
\(C - B \leq a\) ②
\(C - A \leq b\) ③
我们想要知道 \(C - A\) 的最大值,通过 ① \(+\) ②,可以得到 \(C - A \leq a + c\) ,所以这个问题其实就是求 \(min(b , a + c)\)
三角不等式推广到 \(m\) 个,变量推广为 \(n\) 个,就变成 \(n\) 个点 \(m\) 条边的最短路问题。
LuckyBlock 杀人啦。。。
Kersen 也杀人啦。。。
代码
bool SPFA_bfs(int st)
{
queue<int> q;
memset(cnt, 0, sizeof(cnt));
memset(vis, 0, sizeof(vis));
memset(dis, 63, sizeof(dis));
q.push(st);
dis[st] = 0;
vis[st] = true;
while (!q.empty())
{
int u_ = q.front();
q.pop();
vis[u_] = false;
for (int i = head[u_]; i; i = e[i].nxt)
{
int v_ = v[i];
if (dis[v_] > e[i].dis + dis[u_])
{
dis[v_] = dis[u_] + e[i].dis;
cnt[v_] = cnt[u_] + 1;
if (cnt[v_] > n)
return true;
if (!vis[v_])
{
q.push(v_);
vis[v_] = true;
}
}
}
}
return false;
}
未完待续,持续更新~