On differential constraint

Keywords: C++ Algorithm Graph Theory

On differential constraint

It's still a difficult thing.

introduce

Consider a limitation A i ≤ x i + C i A_i \le x_i + C_i Ai ≤ xi + Ci where x i x_i xi is a given value.

A , C A, C A. C represents the relationship between two locations.

Found that for the same A i A_i Ai has several restrictions in total, which means A = min ⁡ i ( x i + C i ) A = \min_i(x_i + C_i) A=mini​(xi​+Ci​).

Finding this thing is the shortest update.

Let's think from another angle, for each C i C_i Ci , the corresponding limitation is C i ≥ A i − x i C_i \ge A_i - x_i Ci ≥ Ai − xi, which means C i = max ⁡ ( A i − x i ) C_i = \max(A_i - x_i) Ci = max(Ai − xi) this is the longest way.

So when the problem does not give some restrictions, we can convert the longest path and the shortest path to each other.

realization

It is often said that this thing needs to be used S P F A \tt SPFA SPFA, in fact F l o y d , D i j k s t r a \tt Floyd, Dijkstra Floyd and Dijkstra are also totally OK. The main problem is B e l l m a n − F o l d \tt Bellman-Fold Bellman − Fold algorithms can judge negative rings, and we can clearly know whether there is a solution.

Of course, it's OK to run the longest way.

Negative ring

If a point joins the team more than all points, there must be a ring.

Consider the length of the path c t i ct_i cti, updated c t u + 1 → c t i ct_u + 1\to ct_i ctu + 1 → cti where u → i u \to i u→i.

The difference between the longest path and the shortest path

The shortest path is the conditional maximum solution, and the longest path is the conditional minimum solution.

This specific proof can be found online.

More often, we need to judge whether we are seeking the maximum solution or the minimum solution according to the problem.

Common examples:

board

Multiplicative addition

P4926 [1007] double kill the measurer

P4926 [1007] double kill the measurer

Limitations are such as:

  • A ( K + T ) ≤ B A(K + T) \le B A(K+T) ≤ B.

We can consider taking logarithms on both sides, that is, it becomes log ⁡ A + log ⁡ ( K + T ) ≤ log ⁡ B \log A + \log(K + T) \le \log B logA+log(K+T)≤logB.

Application of maximum and minimum values

P2474 [SCOI2008] balance

P2474 [SCOI2008] balance

The topic says that it is possible to determine the value. We consider calculating the minimum and maximum values at the same time, and then directly consider turning persimmon into persimmon A − x   B − y A - x\ B - y A−x   B − y, and then enumerate and compare on both sides.

Complexity is O ( n 3 ) O(n^3) O(n3).

transformation

AT5147 [AGC036D] Negative Cycle

AT5147 [AGC036D] Negative Cycle

There is no negative ring in the figure, indicating S P F A \tt SPFA SPFA is solvable, we might as well consider it d i d_i di represents a point i i i distance point 0 0 0.

We create a new point 0 0 0 to represent the point before the first position.

There are obvious limitations d i ≥ d i + 1 , 0 ≤ d i − d i − 1 ≤ 1 d_i \ge d_{i + 1}, 0 \le d_i - d_{i - 1} \le 1 Di ≥ di+1, 0 ≤ di − di − 1 ≤ 1, we can select the strict one.

consider a i = d i − d i + 1 a_i = d_i - d_{i + 1} ai = di − di+1 a a a yes 0 , 1 0, 1 One of 0,1.

After that, you can consider that each point is 0 0 0 or 1 1 1. Consider one d p \tt dp dp, set f ( i , j ) f(i, j) f(i,j) indicates the position i i i yes 1 1 1. The last one is 1 1 The position of 1 is j j j.

The transfer is obviously an enumeration k k k, and then consider when it is legal, because the difference is 1 1 1 so there can be no − 1 -1 − 1, and for [ k , j ] , [ j , i ] [k, j], [j, i] [k,j],[j,i] if there is a left connection between the two positions, there is a right connection − 1 -1 − 1 side has no effect, if any [ j , n ] [j, n] [j,n] 1 1 1 edge will lead to the link between the back position and the front position, resulting in smaller results. This is also not possible.

#include <bits/stdc++.h>
using namespace std;

//#define Fread
//#define Getmod

#ifdef Fread
char buf[1 << 21], *iS, *iT;
#define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
#define getchar gc
#endif // Fread

template <typename T>
void r1(T &x) {
	x = 0;
	char c(getchar());
	int f(1);
	for(; c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
	for(; '0' <= c && c <= '9';c = getchar()) x = (x * 10) + (c ^ 48);
	x *= f;
}

template <typename T,typename... Args> inline void r1(T& t, Args&... args) {
    r1(t);  r1(args...);
}

#ifdef Getmod
const int mod  = 1e9 + 7;
template <int mod>
struct typemod {
    int z;
    typemod(int a = 0) : z(a) {}
    inline int inc(int a,int b) const {return a += b - mod, a + ((a >> 31) & mod);}
    inline int dec(int a,int b) const {return a -= b, a + ((a >> 31) & mod);}
    inline int mul(int a,int b) const {return 1ll * a * b % mod;}
    typemod<mod> operator + (const typemod<mod> &x) const {return typemod(inc(z, x.z));}
    typemod<mod> operator - (const typemod<mod> &x) const {return typemod(dec(z, x.z));}
    typemod<mod> operator * (const typemod<mod> &x) const {return typemod(mul(z, x.z));}
    typemod<mod>& operator += (const typemod<mod> &x) {*this = *this + x; return *this;}
    typemod<mod>& operator -= (const typemod<mod> &x) {*this = *this - x; return *this;}
    typemod<mod>& operator *= (const typemod<mod> &x) {*this = *this * x; return *this;}
    int operator == (const typemod<mod> &x) const {return x.z == z;}
    int operator != (const typemod<mod> &x) const {return x.z != z;}
};
typedef typemod<mod> Tm;
#endif

#define int long long
const int maxn = 5e2 + 5;
const int maxm = maxn << 1;

int A[maxn][maxn], B[maxn][maxn], a[maxn][maxn];
int n;
int Val(int k,int j,int i) {
    return B[j + 1][i] + a[n][j] - a[n][k] - a[i][j] + a[i][k];
}
int f[maxn][maxn];

signed main() {
//    freopen("S.in", "r", stdin);
//    freopen("S.out", "w", stdout);
    int i, j;
    r1(n);
    for(i = 1; i <= n; ++ i) {
        for(j = 1; j <= n; ++ j) if(i != j) r1(a[i][j]);
    }
    for(j = 1; j <= n; ++ j)
        for(i = j; i >= 1; -- i)
            B[i][j] = B[i + 1][j] + a[i][j] + B[i][j - 1] - B[i + 1][j - 1];
    for(i = 1; i <= n; ++ i) for(j = 1; j <= n; ++ j)
        a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
    int ans(1e18);
    for(i = 1; i < n; ++ i) {
        f[i][0] = Val(0, 0, i);
        ans = min(ans, f[i][0] + Val(0, i, n));
        for(j = 1; j < i; ++ j) {
            f[i][j] = 1e18;
            for(int k = 0; k < j; ++ k) {
                f[i][j] = min(f[i][j], f[j][k] + Val(k, j, i));
            }
            ans = min(ans, f[i][j] + Val(j, i, n));
        }
    }
    printf("%lld\n", ans);

	return 0;
}

Posted by zulx on Wed, 13 Oct 2021 21:54:10 -0700