Algorithm learning notes: differential constraints

Posted by one on Mon, 03 Jan 2022 07:39:58 +0100

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>
{
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()
{
queue<int> q;
rep(i, 1, m)
{   int u, v, w;
g[u].pb({v, w});
}
rep(i, 1, n)
{
g.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;
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 << ' ';
}
}

Topics: Algorithm Graph Theory