最小费用最大流Dinic

每条边单位流量会花费价值,在跑出最大流的情况下要求费用最小

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 5e3 + 5;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
    return x * f;
}

struct Edge {
    int n, t, f, c;
}e[N*20];
int h[N], edc = 1;

void Add(int x, int y, int f, int c) {
    e[++edc] = (Edge) {h[x], y, f, c}; h[x] = edc;
}

bool v[N];
int n, m, s, t, d[N], ans, sum;

bool Spfa() {
    memset(v + 1, 0, n);
    memset(d, 0x3f, n * 4 + 4);
    queue<int> q; q.push(s); d[s] = 0;
    while (!q.empty()) {
        int x = q.front(); q.pop(); v[x] = 0;
        for (int i = h[x], y; i; i = e[i].n) {
            if (!e[i].f || d[y=e[i].t] <= d[x] + e[i].c) continue;
            d[y] = d[x] + e[i].c;
            if (!v[y]) q.push(y), v[y] = 1;
        }
    }
    return d[t] != d[0];
}

int Dinic(int x, int lim) {
    if (x == t) return lim;
    int sum = 0; v[x] = 1;
    for (int i = h[x], y; i && lim; i = e[i].n) {
        if (!e[i].f || d[y=e[i].t] != d[x] + e[i].c || v[y]) continue;
        int f = Dinic(y, min(lim, e[i].f));
        lim -= f; sum += f;
        e[i].f -= f; e[i^1].f += f;
    }
    if (!sum) d[x] = d[0];
    return sum;
}

int main() {
    n = read(); m = read(); s = read(); t = read();
    while (m--) {
        int x = read(), y = read(), f = read(), c = read();
        Add(x, y, f, c); Add(y, x, 0, -c);
    }
    while (Spfa()) {
        int f = Dinic(s, 2e9);
        ans += f; sum += f * d[t];
    }
    printf("%d %d
", ans, sum);
    return 0;
}
原文地址:https://www.cnblogs.com/shawk/p/14422910.html