形如题目中描述的有多个不等式的不等式组,让求解一组可行解的,可以用差分约束算法求解,不难从这些不等式中发现,不等式的形式形如求解最短路/最长路问题的形式,那么对于每个约束条件,我们进行移项可得,我们考虑建图跑最短路,那么应该建立从指向的一条边权为的有向边,最初为了找到源点,可以设定一个超级源i=0,并且该点到其他所有点及自身的距离都为0,那么求解的就是一组可行的解的,值得注意的是,跑最短路时如果存在负环,是不存在可行解的,可以用spfa或者bellman-ford判断负环。另外,该类型题也可以考虑求解最长路,将边权取反,判断负环的操作改成判断正环,效果相同
AC代码:
#include <bits/stdc++.h> using namespace std; using LL = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<vector<pair<int, int>>> G(n + 1); for (int i = 0; i < m; i++) { int u, v, c; cin >> u >> v >> c; G[v].push_back(make_pair(u, c)); } for (int i = 1; i <= n; i++) { G[0].push_back(make_pair(i, 0)); } queue<int> q; vector<int> dist(n + 1, 0x3f3f3f3f); vector<int> cnt(n + 1); vector<bool> vis(n + 1); q.push(0); dist[0] = 0; vis[0] = true; cnt[0] = 1; bool ok = false; while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (auto v : G[u]) { if (dist[v.first] > dist[u] + v.second) { dist[v.first] = dist[u] + v.second; cnt[v.first]++; if (cnt[v.first] > n) { ok = true; break; } if (!vis[v.first]) { q.push(v.first); vis[v.first] = true; } } } if (ok) { break; } } if (ok) { cout << "NO\n"; } else { for (int i = 1; i <= n; i++) { cout << dist[i] << " \n"[i == n]; } } return 0; }
浅谈差分约束算法
最新推荐文章于 2024-09-06 10:38:06 发布