• 『笔记』差分约束系统


    定义

    是个啥???

    如果一个系统由 \(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;
    }
    

    未完待续,持续更新~

  • 相关阅读:
    C# 删除指定目录下的所有文件及文件夹
    C# 数组集合分页 Skip Take
    MongoDB模糊查询 工具
    C# skip 重试执行代码段
    C# 加载配置文件
    消息队列MSMQ的使用
    C#中const和readonly的区别
    JSP页面中的tab页
    使用jquery获取单选按钮radio的值
    JSP页面获取下来框select选中项的值和文本的方法
  • 原文地址:https://www.cnblogs.com/Frather/p/14367153.html
Copyright © 2020-2023  润新知