【学习笔记】网络流板子集合

最大流 / 最小割

const long long inf = 0x3f3f3f3f3f3f3f3f;
struct Graph {
    int fst[MAXN], nxt[MAXM], to[MAXM], tot;
    int now[MAXN], d[MAXN];
    long long f[MAXM];
    int s, t;
    Graph() : tot(1) {}
    void init() {
        memset(fst, 0, sizeof fst);
        s = t = 0;
        tot = 1;
    }
    int add(int u, int v, long long w) {
        to[++tot] = v, nxt[tot] = fst[u], fst[u] = tot, f[tot] = w;
        to[++tot] = u, nxt[tot] = fst[v], fst[v] = tot, f[tot] = 0;
        return tot - 1;
    }
    bool bfs() {
        memset(d, 0, sizeof d);
        memcpy(now, fst, sizeof fst);
        queue<int> q; q.push(s); d[s] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = fst[u], v = to[i]; i; i = nxt[i], v = to[i]) if (f[i] && !d[v]) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
        return d[t];
    }
    long long dfs(int u, long long flow) {
        if (u == t) return flow;
        long long rest = flow;
        for (int &i = now[u], v = to[i]; i; i = nxt[i], v = to[i]) {
            if (f[i] && d[v] == d[u] + 1) {
                long long k = dfs(v, min(rest, f[i]));
                if (!k) d[v] = 0;
                rest -= k, f[i] -= k, f[i ^ 1] += k;
            }
            if (!rest) break;
        }
        return flow - rest;
    }
    long long dinic() {
        long long flow, maxflow = 0;
        while (bfs()) while (flow = dfs(s, inf)) maxflow += flow;
        return maxflow;
    }
} g;

最小费用最大流

const long long INF = 0x3f3f3f3f3f3f3f3f;
struct Graph {
    int fst[MAXN], now[MAXN], s, t;
    long long d[MAXN], f[MAXM], c[MAXM];
    int nxt[MAXM], to[MAXM], tot;
    void add(int u, int v, long long w, long long d) {
        to[++tot] = v, nxt[tot] = fst[u], f[tot] = w, c[tot] = d, fst[u] = tot;
        to[++tot] = u, nxt[tot] = fst[v], f[tot] = 0, c[tot] = -d, fst[v] = tot;
    }
    Graph() : tot(1) {}
    bool vis[MAXN];
    bool spfa() {
        memset(d, 0x3f, sizeof d);
        memcpy(now, fst, sizeof fst);
        queue<int> q; d[s] = 0, vis[s] = 1, q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            vis[u] = 0;
            for (int i = fst[u], v = to[i]; i; i = nxt[i], v = to[i]) {
                if (f[i] && d[u] + c[i] < d[v]) {
                    d[v] = d[u] + c[i];
                    if (!vis[v]) vis[v] = 1, q.push(v);
                } 
            }
        }
        return d[t] != INF;
    }
    long long dfs(int u, long long flow, long long &cost) {
        if (u == t) return flow;
        long long rest = flow;
        vis[u] = 1;
        for (int &i = now[u], v = to[i]; i; i = nxt[i], v = to[i]) {
            if (!vis[v] && f[i] && d[v] == d[u] + c[i]) {
                long long k = dfs(v, min(rest, f[i]), cost);
                if (!k) d[v] = -1;
                f[i] -= k, f[i ^ 1] += k, rest -= k, cost += c[i] * k;
            }
            if (!rest) break;
        }
        vis[u] = 0;
        return flow - rest;
    }
    pair<long long, long long> dinic() {
        long long flow, maxflow = 0, cost = 0;
        while (spfa())
            while (flow = dfs(s, INF, cost)) maxflow += flow;
        return { maxflow, cost };
    }
} g;

有源汇上下界最大流

const int inf = INT_MAX / 2;
struct Graph {
    int fst[MAXN], nxt[MAXM], to[MAXM], f[MAXM], now[MAXN], d[MAXN], tot;
    int s, t;
    int in[MAXN], out[MAXN];
    int ncnt; int operator()() { return ++ncnt; } // 点数
    void init() {
        tot = 1, ncnt = 0;
        memset(fst, 0, sizeof fst);
        memset(in, 0, sizeof in);
        memset(out, 0, sizeof out);
    }
    int add(int u, int v, int l, int r) {
        to[++tot] = v, f[tot] = r - l, nxt[tot] = fst[u], fst[u] = tot;
        to[++tot] = u, f[tot] = 0, nxt[tot] = fst[v], fst[v] = tot;
        in[v] += l, out[u] += l;
        return tot - 1;
    }
    bool bfs() {
        memset(d, 0, sizeof d);
        memcpy(now, fst, sizeof fst);
        queue<int> q; q.push(s); d[s] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = fst[u], v = to[i]; i; i = nxt[i], v = to[i]) {
                if (f[i] && !d[v]) {
                    q.push(v);
                    d[v] = d[u] + 1;
                    if (v == t) return true;
                }
            }
        }
        return false;
    }
    int dfs(int u, int flow) {
        if (u == t) return flow;
        int rest = flow;
        for (int &i = now[u], v = to[i]; i; i = nxt[i], v = to[i]) {
            if (f[i] && d[v] == d[u] + 1) {
                int k = dfs(v, min(rest, f[i]));
                if (!k) d[v] = 0;
                f[i] -= k, f[i ^ 1] += k, rest -= k;
            }
            if (!rest) break;
        }
        return flow - rest;
    }
    int dinic(int S, int T) {
        s = S, t = T;
        int flow, maxflow = 0;
        while (bfs()) while (flow = dfs(S, inf)) maxflow += flow;
        return maxflow;
    }
    int solve(int S, int T) {
        int k = add(T, S, 0, inf);
        int ss = ++ncnt, tt = ++ncnt;
        int sum = 0;
        for (int i = 1; i <= ncnt; i++) {
            if (in[i] > out[i]) add(ss, i, 0, in[i] - out[i]), 
                sum += in[i] - out[i];
            if (in[i] < out[i]) add(i, tt, 0, out[i] - in[i]);
        }
        if (dinic(ss, tt) != sum) return -1; // 可行流到这里就结束
        int ans = f[k ^ 1];
        f[k] = f[k ^ 1] = 0;
        return ans + dinic(S, T);
        // 最小流:ans - dinic(T, S);
    }
}g;

有源汇上下界最小费用可行流

const int inf = 0x3f3f3f3f;
struct Graph {
    int fst[MAXN], nxt[MAXM], to[MAXM], f[MAXM], now[MAXN], d[MAXN], tot;
    int c[MAXM];
    bool vis[MAXN];
    int s, t, in[MAXN], out[MAXN], sum;
    int ncnt; int operator()() { return ++ncnt; } // 点数
    void init() {
        tot = 1, ncnt = 0;
        memset(fst, 0, sizeof fst);
        memset(in, 0, sizeof in);
        memset(out, 0, sizeof out);
    }
    void add(int u, int v, int l, int r, int V) {
        to[++tot] = v, f[tot] = r - l, nxt[tot] = fst[u], fst[u] = tot, c[tot] = V;
        to[++tot] = u, f[tot] = 0, nxt[tot] = fst[v], fst[v] = tot, c[tot] = -V;
        sum += l * V;
        in[v] += l, out[u] += l;
    }
    bool spfa() {
        memset(d, 0x3f, sizeof d);
        memcpy(now, fst, sizeof fst);
        queue<int> q; d[s] = 0, vis[s] = 1; q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop(); vis[u] = 0;
            for (int i = fst[u], v = to[i]; i; i = nxt[i], v = to[i]) {
                if (f[i] && d[v] > d[u] + c[i]) {
                    d[v] = d[u] + c[i];
                    if (!vis[v]) vis[v] = 1, q.push(v);
                }
            }
        }
        return d[t] != inf;
    }
    int dfs(int u, int flow, int &cost) {
        if (u == t) return flow;
        int rest = flow;
        vis[u] = 1;
        for (int &i = now[u], v = to[i]; i; i = nxt[i], v = to[i]) {
            if (!vis[v] && f[i] && d[v] == d[u] + c[i]) {
                int k = dfs(v, min(rest, f[i]), cost);
                if (!k) d[v] = -1;
                f[i] -= k, f[i ^ 1] += k, rest -= k, cost += k * c[i];
            }
            if (!rest) break;
        }
        vis[u] = 0;
        return flow - rest;
    }
    int solve() {
        int ss = ++ncnt, tt = ++ncnt;
        s = ss, t = tt;
        for (int i = 1; i <= ncnt; i++) {
            if (in[i] < out[i]) add(i, tt, 0, out[i] - in[i], 0);
            if (in[i] > out[i]) add(ss, i, 0, in[i] - out[i], 0);
        }
        int flow, maxflow = 0, cost = 0;
        while (spfa())
            while (flow = dfs(ss, inf, cost)) maxflow += flow;
        return cost + sum;
    }
}g;
posted @ 2023-01-18 21:44  APJifengc  阅读(25)  评论(0编辑  收藏  举报