首页 > 技术文章 > 『笔记』差分约束系统

Frather 2021-02-03 15:15 原文

定义

是个啥???

如果一个系统由 \(n\) 个变量和 \(m\) 个约束条件组成,形成 \(m\) 个形如 \(x_i - y_i \leq k\) 的不等式( \(i,j \in [ 1 , n ]\)\(k\) 为常数),则称其为差分约束系统( \(system\) \(of\) \(difference\) \(constraints\))。

亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。

说句人话就是:

差分约束系统就是给出一些形如 \(x - y \leq b\) 不等式的约束,问你是否有满足问题的解,或者求最小最大解

实现

这类问题的 \(NB\) 之处就是可以转化为图论的最短路问题。

瞎搞

\[x_i - x_j \leq a_k \]

\[x_i \leq x_j + a_k \]

\(a_k = w(j,i)\) ,则有

\[x_i \leq x_j + w(j,i) \]

\(i = to\)\(j = from\)\(x = dis\) ,则有

\[dis_{to} \leq dis_{from} + w(from,to) \]

\(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;
}

未完待续,持续更新~

推荐阅读