[P5960] 【模板】差分约束算法 - 差分约束
Description
给出一组包含 (m) 个不等式,有 (n) 个未知数的形如:
[egin{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_mend{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;
}