费用流(最小费用可行流)
struct MCFGraph { struct Edge { int v, c, f; Edge(int v, int c, int f) : v(v), c(c), f(f) {} }; const int n; vector<Edge> e; vector<vector<int>> g; vector<i64> h, dis; vector<int> pre; bool dijkstra(int s, int t) { dis.assign(n, numeric_limits<i64>::max()); pre.assign(n, -1); priority_queue<pair<i64, int>, vector<pair<i64, int>>, greater<pair<i64, int>>> que; dis[s] = 0; que.emplace(0, s); while (!que.empty()) { i64 d = que.top().first; int u = que.top().second; que.pop(); if (dis[u] < d) continue; for (int i : g[u]) { int v = e[i].v; int c = e[i].c; int f = e[i].f; if (c > 0 && dis[v] > d + h[u] - h[v] + f) { dis[v] = d + h[u] - h[v] + f; pre[v] = i; que.emplace(dis[v], v); } } } return dis[t] != numeric_limits<i64>::max(); } MCFGraph(int n) : n(n), g(n) {} // c 是流量限制,f 是单位费用 void addEdge(int u, int v, int c, int f) { if (f < 0) { g[u].push_back(e.size()); e.emplace_back(v, 0, f); g[v].push_back(e.size()); e.emplace_back(u, c, -f); } else { g[u].push_back(e.size()); e.emplace_back(v, c, f); g[v].push_back(e.size()); e.emplace_back(u, 0, -f); } } pair<int, i64> flow(int s, int t) { int flow = 0; i64 cost = 0; h.assign(n, 0); while (dijkstra(s, t)) { for (int i = 0; i < n; ++i) h[i] += dis[i]; int aug = numeric_limits<int>::max(); for (int i = t; i != s; i = e[pre[i] ^ 1].v) aug = min(aug, e[pre[i]].c); for (int i = t; i != s; i = e[pre[i] ^ 1].v) { e[pre[i]].c -= aug; e[pre[i] ^ 1].c += aug; } flow += aug; cost += i64(aug) * h[t]; } return make_pair(flow, cost); }};// 点数 5e3,边数 5e4