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>
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 << ' ';
    }
}

Topics: Algorithm Graph Theory