[P5960] 【模板】差分约束算法 - 差分约束

Description

给出一组包含 \(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} \]

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

Solution

差分约束,给出的式子为 \(x_c-x_{c'} \le y\),我们转化为 \(x_c \le x_{c'}+y\),于是 \(c'\)\(c\) 连边,边权为 \(y\)

添加超级源点 \(S\),向所有点 \(i\) 连权为 \(0\) 的边,跑最短路即可

负环的判定基于普通 SPFA,如果一个点的入队次数超过 \(n\) 则判定存在负环

#include <bits/stdc++.h>
using namespace std;

const int N = 5005;

int dis[N], vis[N], cnt[N], n, m;
vector<pair<int, int>> g[N];

signed main()
{
    ios::sync_with_stdio(false);

    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int c, c1, y;
        cin >> c >> c1 >> y;
        g[c1].push_back({c, y});
    }
    for (int i = 1; i <= n; i++)
    {
        g[0].push_back({i, 0});
    }

    queue<int> que;
    que.push(0);
    memset(dis, 0x3f, sizeof dis);
    dis[0] = 0;
    vis[0] = 1;
    cnt[0] = 1;
    while (que.size())
    {
        int p = que.front();
        que.pop();
        vis[p] = 0;
        for (auto [q, w] : g[p])
        {
            if (dis[q] > dis[p] + w)
            {
                dis[q] = dis[p] + w;
                if (vis[q] == 0)
                {
                    vis[q] = 1;
                    que.push(q);
                    cnt[q]++;
                    if (cnt[q] > n)
                    {
                        cout << "NO" << endl;
                        return 0;
                    }
                }
            }
        }
    }
    for (int i = 1; i <= n; i++)
        cout << dis[i] << " ";
    cout << endl;
}

相关文章:

  • 2021-11-29
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-10-13
  • 2022-03-05
  • 2021-09-26
相关资源
相似解决方案