差分约束系统

差分约束系统

线性规划

在通用线性规划问题中,我们通常给定一个矩阵 A A A,和一个未知向量 → x \underset{x}{\rightarrow} x,和一个已知向量 → b \underset{b}{\rightarrow} b。求解矩阵不等式 A x ≤ b Ax \leq b Axb。有时候我们并不关心目标函数,而是希望计算出一个可行解(或告知无解)。

差分约束系统

在一个差分约束系统中,线性规划矩阵 A A A每一个都有且仅有一个1和-1,其他位置均为0。因此,由 A x ≤ b Ax \leq b Axb所给出的差分约束系统是由m个约束条件,n个变量差额限制条件,其中每一个约束条件都是类似于下面的不等式 x i − x j ≤ b k x_{i} - x_{j} \leq b_{k} xixjbk,其中m为A的行数,n为A的列数, 1 ≤ i , j ≤ n , i ≠ j 1 \leq i,j \leq n,i \neq j 1i,jn,i=j并且 1 ≤ k ≤ m 1 \leq k \leq m 1km

定理:如果 x x x是差分约束系统的一个可行解,那么对于任意整数 d d d,则向量 x + d i x+di x+di同样是差分约束系统的一个可行解,其中 i i i为全部元素都是1的向量。

将d加到每一个 x i x_{i} xi上面,对于约束条件做减法的时候,d就会被消掉,因此加上一个常数向量还是一个可行解。

约束图

给定差分约束系统,其对应的约束图是有向图 G = ( V , E ) G=(V,E) G=(V,E) V = ( v 0 , v 1 , ⋯   , v n ) V=(v_{0},v_{1},\cdots,v_{n}) V=(v0,v1,,vn) E = { ( v i , v j ) : x j − x i ≤ b k } ∪ { ( v 0 , v 1 ) , ( v 0 , v 2 ) , ⋯   , ( v 0 , v k ) } E=\{ (v_{i},v_{j}):x_{j} - x_{i} \leq b_{k} \} \cup \{ (v_{0},v_{1}) , (v_{0},v_{2}) , \cdots ,(v_{0},v_{k})\} E={(vi,vj):xjxibk}{(v0,v1),(v0,v2),,(v0,vk)}

对于权值函数 w w w的定义, w 0 j = 0 , w i j = b k w_{0j} = 0,w_{ij} = b_{k} w0j=0,wij=bk。下面的定义将把差分约数系统和图论最短路建立关系。

定理:差分约数系统的一个可行解为, x = ( δ ( v 0 , v 1 ) , δ ( v 0 , v 2 ) , ⋯   , δ ( v 0 , v n ) ) x=(\delta(v_{0},v_{1}),\delta(v_{0},v_{2}),\cdots,\delta(v_{0},v_{n})) x=(δ(v0,v1),δ(v0,v2),,δ(v0,vn))

证明:考虑任意一条边 ( v i , v j ) (v_{i},v_{j}) (vi,vj),根据三角不等式有, δ ( v 0 , v j ) ≤ δ ( v 0 , v i ) + w i j \delta(v_{0},v_{j}) \leq \delta(v_{0},v_{i}) + w_{ij} δ(v0,vj)δ(v0,vi)+wij,即 δ ( v 0 , v j ) − δ ( v 0 , v i ) ≤ w i j \delta(v_{0},v_{j}) - \delta(v_{0},v_{i}) \leq w_{ij} δ(v0,vj)δ(v0,vi)wij,又因为 x i = δ ( v 0 , v i ) , x j = δ ( v 0 , v j ) x_{i} = \delta(v_{0},v_{i}),x_{j} = \delta(v_{0},v_{j}) xi=δ(v0,vi),xj=δ(v0,vj),因此 x j − x i ≤ w i j = b k x_{j} - x_{i} \leq w_{ij} = b_{k} xjxiwij=bk

定理:如果约束图存在负权环,则差分约束系统无解。

证明:反证法,详情查看《算法导论》。

求解差分约数系统

可以选择运行一遍BellmanFord算法,也可以进行SPFA优化。

P1993

注意条件转化,在求解 d n dn dn数组的时候,注意到初始化不能设置成最大的数组,否则相加的时候会出现溢出的问题。

以下是Bellman-Ford判断负环算法。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define FR freopen("in.txt", "r", stdin)

struct Edge
{
    int from;
    int to;
    ll w;
} e[20005];

ll dn[6000];

int tot = 0;
int n, m;

inline void add(int u, int v, ll w)
{
    tot++;
    e[tot].from = u;
    e[tot].to = v;
    e[tot].w = w;
}

int main()
{
    cin >> n >> m;

    while (m--)
    {
        int op, u, v;
        cin >> op >> u >> v;

        if (op == 1)
        {
            ll c;
            cin >> c;
            add(u, v, -c);
        }
        else if (op == 2)
        {
            ll c;
            cin >> c;
            add(v, u, c);
        }
        else if (op == 3)
        {
            add(u, v, 0);
            add(v, u, 0);
        }
    }

    for (int i = 1; i <= n; i++)
    {
        add(0, i, 0);
        dn[i] = 1000000007;
    }

    dn[0] = 0;

    // negi loop


    for (int cnt = 0; cnt < n; cnt++)
    {
        for (int i = 1; i <= tot; i++)
        {
            Edge curr = e[i];
            if (dn[curr.to] > dn[curr.from] + curr.w)
            {
                dn[curr.to] = dn[curr.from] + curr.w;
            }
        }
    }

    for (int i = 1; i <= tot; i++)
    {
        Edge curr = e[i];
        if (dn[curr.to] > dn[curr.from] + curr.w)
        {
            cout << "No";
            return 0;
        }
    }

    cout << "Yes";

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值