【模板】差分约束

发布时间 2023-12-10 02:32:26作者: potential-star

给出一组包含 \(m\) 个不等式,有 \(n\) 个未知数的形如:

\[\begin{cases} x_{c_1}-x_{c'_1}\leq y_1 \\x_{c_2}-x_{c'_2} \leq y_2 \\ \cdots\\ x_{c_m} - x_{c'_m}\leq y_m\end{cases} \]

的不等式组,求任意一组满足这个不等式组的解。

输入格式

第一行为两个正整数 \(n,m\),代表未知数的数量和不等式的数量。

接下来 \(m\) 行,每行包含三个整数 \(c,c',y\),代表一个不等式 \(x_c-x_{c'}\leq y\)

数据范围

对于 \(100\%\) 的数据,\(1\leq n,m \leq 5\times 10^3\)\(-10^4\leq y\leq 10^4\)\(1\leq c,c'\leq n\)\(c \neq c'\)

#define MAXN 5005
#define MAXM 10005
using namespace std;
int read()
{
    int ans = 0, sgn = 1;
    char c = getchar();
    while (!isdigit(c))
    {
        if (c == '-')
            sgn *= -1;
        c = getchar();
    }
    while (isdigit(c))
    {
        ans = ans * 10 + c - '0';
        c = getchar();
    }
    return ans * sgn;
}
int cnt_edge, head[MAXN];
struct
{
    int to, next, w;
} edges[MAXM];
void add_edge(int from, int to, int w)
{
    edges[++cnt_edge].next = head[from];
    edges[cnt_edge].to = to;
    edges[cnt_edge].w = w;
    head[from] = cnt_edge;
}
bool inqueue[MAXN];
int cnt[MAXN], dis[MAXN];
queue<int> Q;
bool SPFA(int s, int n)
{
    memset(dis, 127, sizeof(dis));
//  memset(dis, -127, sizeof(dis));
    dis[s] = 0;
    Q.push(s);
    while (!Q.empty())
    {
        int p = Q.front();
        if (cnt[p] > n)
            return false;
        Q.pop();
        inqueue[p] = false;
        for (int eg = head[p]; eg != 0; eg = edges[eg].next)
        {
            int to = edges[eg].to;
            if (edges[eg].w + dis[p] < dis[to])
//          if (edges[eg].w + dis[p] > dis[to])
            {
                dis[to] = edges[eg].w + dis[p];
                if (!inqueue[to])
                {
                    Q.push(to);
                    inqueue[to] = true;
                    cnt[to]++;
                }
            }
        }
    }
    return true;
}
int main()
{
    int n = read(), m = read();
    for (int i = 0; i < m; ++i)
    {
        int x = read(), y = read(), w = read();
        add_edge(y, x, w);
//      add_edge(x, y, -w);
    }
    for (int i = 1; i <= n; ++i)
        add_edge(0, i, 0);
    if (SPFA(0, n))
    {
        for (int i = 1; i <= n; ++i)
            printf("%d ", dis[i]);
    }
    else
        puts("NO");
    return 0;
}