概述

差分约束(Difference Constraints) 是一类特殊的线性不等式系统,形式为:

其中 为变量下标, 为常数。1

差分约束广泛应用于调度问题、区间分配、资源分配等场景。

转化为最短路问题

对于不等式 ,可以构造一条有向边 ,权值为

这与最短路中的松弛操作 形式完全一致。

构造方法

给定 个变量 个约束

  1. 建立源点 ,向所有点 建立边 ,权值为
  2. 对于每个约束 ,建立边 ,权值为
  3. 从源点运行 Bellman-Ford 或 SPFA

若存在负环,则系统无解。

求解算法

Bellman-Ford

struct Edge {
    int u, v, w;
};
 
const int INF = 1e9;
 
bool bellman_ford(int n, int s, const vector<Edge>& edges, vector<long long>& dist) {
    dist.assign(n + 1, INF);
    dist[s] = 0;
    
    // n 个点,松弛 n-1 次
    for (int i = 1; i <= n; i++) {
        bool updated = false;
        for (const auto& e : edges) {
            if (dist[e.u] != INF && dist[e.u] + e.w < dist[e.v]) {
                dist[e.v] = dist[e.u] + e.w;
                updated = true;
            }
        }
        if (!updated) break;
    }
    
    // 第 n 次松弛检查负环
    for (const auto& e : edges) {
        if (dist[e.u] != INF && dist[e.u] + e.w < dist[e.v]) {
            return false;  // 存在负环,无解
        }
    }
    return true;
}

SPFA(队列优化)

bool spfa(int n, int s, const vector<vector<pair<int,int>>>& g, vector<long long>& dist) {
    vector<int> cnt(n + 1, 0);  // 入队次数
    vector<bool> inq(n + 1, false);
    queue<int> q;
    
    dist.assign(n + 1, INF);
    dist[s] = 0;
    q.push(s);
    inq[s] = true;
    
    while (!q.empty()) {
        int u = q.front(); q.pop();
        inq[u] = false;
        
        for (auto [v, w] : g[u]) {
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                if (!inq[v]) {
                    q.push(v);
                    inq[v] = true;
                    if (++cnt[v] > n) return false;  // 负环
                }
            }
        }
    }
    return true;
}

典型应用

1. 区间约束

问题:给定 个区间 ,每个区间至少包含 个点,求满足条件的最小解。

建模

  • 为前 个位置中放置的点数
  • 约束:
  • 转化为

2. Scheduling(工程调度)

问题:有 个任务,任务 必须在任务 完成后才能开始,且需要 时间。求最早完成时间。

建模

3. 差分数组验证

问题:给定数组 ,判断是否存在 使得所有区间和约束满足。

转化:前缀和 ,约束变为

例题:某年到某年

题目(CSP真题简化):有 个学生,第 个学生需要在 时间内至少参加一个活动。安排活动使得总数最少。

思路:差分约束 + 二分答案

建模

  • 为截至时间 已参加活动的学生数
  • 约束:

解的多样性

差分约束的解不唯一。若 是解,则 也是解( 为任意常数)。

通常取最小(或最大)的解,通过改变源点的边权实现。

与其他问题的关系

问题约束形式解法
差分约束SPFA/Bellman-Ford
2-SATSCC缩点
0-1约束差分约束特殊形式

参考


Last updated: 2026-04-06

Footnotes

  1. 本内容参考 OI-Wiki 差分约束,内容经过验证和扩展。