前置知识

差分约束系统

如果一个系统由 n 个变量和 m 个约束条件组成,形成 m 个形如 aiajk 的不等式(i,j[1,n]k 为常数),则称其为差分约束系统。

如何求出一个差分约束系统的解?

aiajkaiaj+k

这类似最短路中的三角不等式 disvdisu+wu,v

对于 aiajk,连接一条权值为 k 的边 ji

最后建立超级源点 0,向各个点连权值为 0 的边。

从超级源点开始跑一遍最短路,就可以求出一组可行解。

无解

正如最短路可能会出现无解情况。如果建出的图中存在负环,则该差分约束系统无解。

模板

Luogu 5960 【模板】差分约束算法

Solution

模板题。根据上述内容做即可。

注意有一个坑点:由于超级源点的存在,实际点数为 n+1,判负环不要写错了。

Code
点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define go(i,x,y) for (int i=x;i<=y;i++)
using namespace std;
template <typename type>
void read(type &x){
    char c=getchar();
    int F=0;
    while (c!='-' && (c<'0' || c>'9')) c=getchar();
    if (c=='-') F=1,x=0; else x=(c^48);
    c=getchar();
    while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if (F) x=-x;
}
template <typename type>
void write(type x){
    if (x<0) putchar('-'),x=-x;
    if (x>9) write(x/10);
    putchar(x%10+'0');
}
const int M=5e3+5,N=5e3+5;
struct edge{
    int to,nex,w;
}e[M+N];
int h[N],hcnt;
void add_edge(int x,int y,int z){
    e[++hcnt]=(edge){y,h[x],z};
    h[x]=hcnt;
}
int n,m,x,y,z,dis[N],cnt[N],vis[N];
queue <int> q;
bool SPFA(int s){
    memset(dis,0x3f,sizeof(dis));
    // memset(vis,0,sizeof(vis));
    // memset(cnt,0,sizeof(cnt));
    while (!q.empty()) q.pop();
    dis[s]=0,vis[s]=1,cnt[s]=1;
    q.push(s);
    while (!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=h[x]; i; i=e[i].nex){
            int y=e[i].to;
            if (dis[x]+e[i].w<dis[y]){
                dis[y]=dis[x]+e[i].w;
                if (!vis[y]){
                    if (++cnt[y]>=n+1) return false;
                    vis[y]=1,q.push(y);
                }
            }
        }
    }
    return true;
}
int main(){
    read(n),read(m);
    go(i,1,m) read(x),read(y),read(z),add_edge(y,x,z);
    go(i,1,n) add_edge(0,i,0);
    if (SPFA(0)){
        go(i,1,n) write(dis[i]),putchar(' ');
    } else{
        puts("NO");
    }
    return 0;
}