最小费用最大流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\n", ans, sum);
return 0;
}