题目大意:最小费用最大流
题解:最小费用最大流
卡点:1.太久不打MCMF,反向弧费用未取相反数
C++ Code:
#include <cstdio> #include <cstring> #define maxn 5010 #define maxm 50100 using namespace std; const int inf = 0x3f3f3f3f; int n, m, S, T, MF; int q[maxm], h, t; int d[maxn], pre[maxn]; bool vis[maxn]; int head[maxn], cnt = 2; struct Edge { int to, nxt, w, cost; } e[maxm << 1]; void add(int a, int b, int c, int d) { e[cnt] = (Edge) {b, head[a], c, d}; head[a] = cnt; e[cnt ^ 1] = (Edge) {a, head[b], 0, -d}; head[b] = cnt ^ 1; cnt += 2; } inline int min(int a, int b) {return a < b ? a : b;} bool spfa() { memset(d, 0x3f, sizeof d); d[q[h = t = 0] = S] = 0; while (h <= t) { int u = q[h++]; vis[u] = false; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (e[i].w && d[v] > d[u] + e[i].cost) { d[v] = d[u] + e[i].cost; pre[v] = i; if (!vis[v]) { q[++t] = v; vis[v] = true; } } } } return d[T] != inf; } int update() { int ans, mf = inf; for (int i = pre[T]; i; i = pre[e[i ^ 1].to]) mf = min(mf, e[i].w); ans = mf * d[T]; MF += mf; for (int i = pre[T]; i; i = pre[e[i ^ 1].to]) e[i].w -= mf, e[i ^ 1].w += mf; return ans; } void MCMF() { int ans = 0; while (spfa()) ans += update(); printf("%d %d ", MF, ans); } int main() { scanf("%d%d%d%d", &n, &m, &S, &T); for (int i = 0; i < m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); add(a, b, c, d); } MCMF(); return 0; }