网络流杂题

Increase to make it Increasing

首先差分,这是毋庸置疑的。

然后问题就转化成每次操作可以给 \(L_i\) 位置 \(+1\),给 \(R_i+1\) 位置 \(-1\),最后要求 \(1\sim n\) 每个位置都是 \(\ge 0\) 的。

这个感觉可以 dp 或者贪心?

应该是一个贪心,因为只需要满足每个位置 \(\ge 0\),所以对于一个 \(\lt 0\) 的位置,考虑对它操作。

好像是可以转化到网络流模型的,就源点向每个 \(d_i\ge 0\)\(i\) 连边,流量是 \(d_i\)(这里表示差分数组),然后每个 \(d_i\lt 0\)\(i\) 向汇点连边,流量是 \(|d_i|\)

特殊的,\(d_{n+1}\)\(inf\)

然后每个操作的 \(R_i+1\)\(L_i\) 连边,流量 \(inf\),费用为 \(1\)

然后跑就行了。

代码
#include <bits/stdc++.h>

void Freopen() {
    freopen("", "r", stdin);
    freopen("", "w", stdout);
}

using namespace std;
const int N = 2e5 + 10, M = 2e5 + 10, inf = 1e9, mod = 998244353;

int n, m, sum;
int a[N], d[N];

int cnt = 1, S, T;

int dis[N], vis[N], dep[N], head[N];

struct edge {
    int to, nxt, w, c;
} E[N];

void add( int x, int y, int z, int p) {
    E[++ cnt] = {y, head[x], z, p}, head[x] = cnt;
    E[++ cnt] = {x, head[y], 0, -p}, head[y] = cnt;
}

bool spfa() {
    for ( int i = 0; i <= T; i ++) dis[i] = inf, vis[i] = 0;
    queue< int> q;
    q.push(S), dis[S] = 0, vis[S] = 1;

    while (q.size()) {
        int u = q.front();
        q.pop(), vis[u] = 0;

        for ( int i = head[u], v; i; i = E[i].nxt)
            if (E[i].w && dis[v = E[i].to] > dis[u] + E[i].c) {
                dis[v] = dis[u] + E[i].c, dep[v] = dep[u] + 1;

                if (! vis[v]) vis[v] = 1, q.push(v);
            }
    }

    return dis[T] != inf;
}

int dfs( int u, int f, int & mco) {
    if (u == T) return f;

    int res = f;
    for ( int i = head[u], v; i; i = E[i].nxt)
        if (E[i].w && dep[v = E[i].to] == dep[u] + 1)
            if (dis[v] == dis[u] + E[i].c) {
                int now = dfs(v, min(E[i].w, res), mco);
                if (! now) dep[v] = 1;
                else {
                    res -= now, mco += E[i].c * now;
                    E[i].w -= now, E[i ^ 1].w += now;
                }

                if (! res) return f;
            }

    return f - res;
}

pair< int, int> dinic() {
    int mxl = 0, mnc = 0;
    while (spfa()) mxl += dfs(S, inf, mnc);
    return {mxl, mnc};
}

signed main() {
    ios :: sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    cin >> n >> m;

    for ( int i = 1; i <= n; i ++) cin >> a[i];
    a[n + 1] = inf;

    for ( int i = 1; i <= n + 1; i ++) d[i] = a[i] - a[i - 1];

    S = n + 2, T = n + 3;

    for ( int i = 1; i <= n + 1; i ++) {
        if (d[i] >= 0) add(S, i, d[i], 0);
        else add(i, T, abs(d[i]), 0), sum += abs(d[i]);
    }

    while (m --) {
        int l, r; cin >> l >> r;
        add(r + 1, l, inf, 1);
    }

    auto res = dinic();

    if (res.first != sum) cout << "-1\n";
    else cout << res.second << '\n';

    return 0;
}
posted @ 2025-09-04 20:31  咚咚的锵  阅读(4)  评论(0)    收藏  举报