Differential constraint
Problem type description
- given n n n variables and m m m constraints, e.g x i − x j ≤ c k x_i-x_j\leq c_k xi − xj ≤ ck, let you find a set of solutions. Yes, all constraints are satisfied.
Model transformation
-
Deform: x i ≤ x j + c k x_i\leq x_j + c_k xi≤xj+ck
- Easy to find, with the most short circuit d i s [ v ] ≤ d i s [ u ] + w dis[v]\leq dis[u]+w dis[v] ≤ dis[u]+w is very similar
-
How to understand?
-
If u u u and v v There is a connecting edge between v, then d i v [ v ] div[v] The value of div[v], do you want it = = d i s [ u ] + w ==dis[u]+w ==dis[u]+w, yes < d i s [ u ] + w <dis[u]+w <dis[u]+w
Because where is the connecting edge, it can be relaxed as long as it is d i s [ v ] > d i s [ u ] + w dis[v]>dis[u]+w Dis [v] > dis [u] + W, then this situation can be relaxed
-
-
Then we transform the inequality problem into a shortest path problem
Progressive thinking
-
Next, our x [ 1 − n ] x[1-n] x[1 − n] is equivalent to d i s [ 1 − n ] dis[1-n] dis[1 − n], and then what we want to solve is d i s [ 1 − n ] dis[1-n] dis[1 − n], that is to solve the shortest path
-
As long as there is a directed edge, it satisfies the condition of that inequality and runs the shortest path to find all the shortest distances d i s [ ] dis[~] dis []
How to select the source point?
-
Because it is a directed graph, we need to traverse all nodes, so we need to establish a super source point No. 0
- We selected a "relationship", so the overall offset is a value, and the answer is still correct
- All nodes to 0 0 The distance of 0 is a fixed value d d d. General blogs are set to 0 0 0, of course, you change to 114514 114514 There is no difference in 114514
- After all, it's just an offset
There is no solution to the inequality system
-
Under what circumstances does the above polynomial group have no solution?
-
In our transformed model, if the shortest distance of a point d i s [ i ] dis[i] dis[i] does not exist, that is, non negative infinity -- > there is a negative ring
In the original equations, several variables are constrained each other
-
Therefore, we can use SPFA to judge the negative ring, that is, there is num [i] > n
Why not use Dijkstra
- Dijkstra cannot handle negative edge weights. It has been established d i s [ ] dis[] If the point of dis [] has negative edge weight, it may be updated by subsequent points.
expand
-
The form of the title is x i − x j ≤ c k x_i-x_j\le c_k xi−xj≤ck
-
if it is x i − x j ≥ c k x_i-x_j\ge c_k xi−xj≥ck
- Then multiply both sides by the minus sign at the same time, with x j − x i ≤ c k x_j-x_i\le c_k xj−xi≤ck
-
if it is x i − x j = c k x_i-x_j=c_k xi − xj = ck, that is, the unity of the above two
- $x_i-x_j\le c_k And And And x_j-x_i\leq c_k $, two-way edges can be established
code implementation
#include <bits/stdc++.h> #include <bits/extc++.h> #include <unordered_map> #include <unordered_set> using namespace std; using namespace __gnu_cxx; using namespace __gnu_pbds; #define debug(x) cerr << #x << ": " << x << '\n'; #define bd cerr << "----------------------" << el; #define el '\n' #define cl putchar('\n'); #define pb push_back #define eb emplace_back #define x first #define y second #define rep(i, a, b) for (int i = (a); i <= (b); i++) #define lop(i, a, b) for (int i = (a); i < (b); i++) #define dwn(i, a, b) for (int i = (a); i >= (b); i--) #define ceil(a, b) (a + (b - 1)) / b #define ms(a, x) memset(a, x, sizeof(a)) #define INF 0x3f3f3f3f #define db double #define all(x) x.begin(),x.end() #define cmax(a, b) a = max(a, b) #define cmin(a, b) a = min(a, b) #define reps(i, x) for (int i = 0; i < x.size(); i++) typedef long long LL; typedef long double LD; typedef pair<int, int> PII; typedef pair<db, db> PDD; typedef vector<int> vci; template <typename T> inline void read(T &x) { x = 0; T f = 1; char c = getchar(); while (!isdigit(c)) { if(c == '-') f = -1; c = getchar(); } while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } x *= f; } const int N = 1e5 + 10, M = 2e6 + 10, B = 66, md = 1e9 + 7; const double PI = acos(-1), eps = 1e-8; int T, n, m; vector<PII> g[N]; int vis[N], dis[N]; bool inq[N]; int main() { read(n), read(m); queue<int> q; rep(i, 1, m) { int u, v, w; read(v), read(u), read(w); g[u].pb({v, w}); } rep(i, 1, n) { g[0].pb({i, 0}); //Establish an edge from 0 to all points //This 0 is just an offset. You can change it to any value } memset(dis, 0x3f, sizeof dis); dis[0] = 0; q.push(0); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] ++ ; inq[u] = false; if(vis[u] > n + 1) { cout << "NO"; exit(0); } #define v g[u][i].first #define w g[u][i].second reps(i, g[u]) { if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; if(!inq[v]) { inq[v] = true; q.push(v); } } } #undef v #undef w } rep(i, 1, n) { cout << dis[i]; if( i < n) cout << ' '; } }