最大流 & 最小割

  • Dinic 网络流 - 图1,求解二分图最大匹配时间复杂度为 网络流 - 图2 ```cpp template struct simple_queue { std::vector payload; int pos = 0; void reserve(int n) { payload.reserve(n); } int size() const { return int(payload.size()) - pos; } bool empty() const { return pos == int(payload.size()); } void push(const T& t) { payload.push_back(t); } T& front() { return payload[pos]; } void clear() {
    1. payload.clear();
    2. pos = 0;
    } void pop() { pos++; } };

template struct mf_graph { public: mf_graph() : _n(0) {} explicit mf_graph(int n) : _n(n), g(n) {}

  1. // 添加 from 到 to,容量为 cap 的边
  2. int add_edge(int from, int to, Cap cap) {
  3. assert(0 <= from && from < _n);
  4. assert(0 <= to && to < _n);
  5. assert(0 <= cap);
  6. int m = int(pos.size());
  7. pos.push_back({from, int(g[from].size())});
  8. int from_id = int(g[from].size());
  9. int to_id = int(g[to].size());
  10. if (from == to) to_id++;
  11. g[from].push_back(_edge{to, to_id, cap});
  12. g[to].push_back(_edge{from, from_id, 0});
  13. return m;
  14. }
  15. struct edge {
  16. int from, to;
  17. Cap cap, flow;
  18. };
  19. // 获取第 i 次 add 的边,返回该边的 {from, to, cap, cur_cap}
  20. edge get_edge(int i) {
  21. int m = int(pos.size());
  22. assert(0 <= i && i < m);
  23. auto _e = g[pos[i].first][pos[i].second];
  24. auto _re = g[_e.to][_e.rev];
  25. return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
  26. }
  27. // 返回所有边
  28. std::vector<edge> edges() {
  29. int m = int(pos.size());
  30. std::vector<edge> result;
  31. for (int i = 0; i < m; i++) {
  32. result.push_back(get_edge(i));
  33. }
  34. return result;
  35. }
  36. // 修改某条边的当前容量 new_cap - new_flow,对应反向边容量为 new_flow
  37. void change_edge(int i, Cap new_cap, Cap new_flow) {
  38. int m = int(pos.size());
  39. assert(0 <= i && i < m);
  40. assert(0 <= new_flow && new_flow <= new_cap);
  41. auto& _e = g[pos[i].first][pos[i].second];
  42. auto& _re = g[_e.to][_e.rev];
  43. _e.cap = new_cap - new_flow;
  44. _re.cap = new_flow;
  45. }
  46. // 求解 s 点到 t 号点的最大流
  47. Cap flow(int s, int t) {
  48. return flow(s, t, std::numeric_limits<Cap>::max());
  49. }
  50. // dinic,求解 s 到 t 的最大流
  51. Cap flow(int s, int t, Cap flow_limit) {
  52. assert(0 <= s && s < _n);
  53. assert(0 <= t && t < _n);
  54. assert(s != t);
  55. std::vector<int> level(_n), iter(_n);
  56. simple_queue<int> que;
  57. auto bfs = [&]() {
  58. std::fill(level.begin(), level.end(), -1);
  59. level[s] = 0;
  60. que.clear();
  61. que.push(s);
  62. while (!que.empty()) {
  63. int v = que.front();
  64. que.pop();
  65. for (auto e : g[v]) {
  66. if (e.cap == 0 || level[e.to] >= 0) continue;
  67. level[e.to] = level[v] + 1;
  68. if (e.to == t) return;
  69. que.push(e.to);
  70. }
  71. }
  72. };
  73. auto dfs = [&](auto self, int v, Cap up) {
  74. if (v == s) return up;
  75. Cap res = 0;
  76. int level_v = level[v];
  77. for (int& i = iter[v]; i < int(g[v].size()); i++) {
  78. _edge& e = g[v][i];
  79. if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue;
  80. Cap d =
  81. self(self, e.to, std::min(up - res, g[e.to][e.rev].cap));
  82. if (d <= 0) continue;
  83. g[v][i].cap += d;
  84. g[e.to][e.rev].cap -= d;
  85. res += d;
  86. if (res == up) return res;
  87. }
  88. level[v] = _n;
  89. return res;
  90. };
  91. Cap flow = 0;
  92. while (flow < flow_limit) {
  93. bfs();
  94. if (level[t] == -1) break;
  95. std::fill(iter.begin(), iter.end(), 0);
  96. Cap f = dfs(dfs, t, flow_limit - flow);
  97. if (!f) break;
  98. flow += f;
  99. }
  100. return flow;
  101. }
  102. //返回最小割,需要提前调用 flow
  103. std::vector<bool> min_cut(int s) {
  104. std::vector<bool> visited(_n);
  105. simple_queue<int> que;
  106. que.push(s);
  107. while (!que.empty()) {
  108. int p = que.front();
  109. que.pop();
  110. visited[p] = true;
  111. for (auto e : g[p]) {
  112. if (e.cap && !visited[e.to]) {
  113. visited[e.to] = true;
  114. que.push(e.to);
  115. }
  116. }
  117. }
  118. return visited;
  119. }

private: int _n; struct _edge { int to, rev; Cap cap; }; std::vector> pos; std::vector> g; };

  1. <a name="jgyE2"></a>
  2. ## 最小费用流
  3. ![](https://cdn.nlark.com/yuque/__latex/98921346cebd0385c2c3194e13a7c3b3.svg#card=math&code=Primal-Dual&id=AEYYn)最小费用最大流,复杂度![](https://cdn.nlark.com/yuque/__latex/1185efd542e780997fe7c2848acd595a.svg#card=math&code=O%28F%20%28n%20%2B%20m%29%20%5Clog%20%28n%20%2B%20m%29%29&id=uJPKE)。<br />以下模版中,边费用必须为非零整数。所以只能用来求解最小费用。
  4. ```cpp
  5. template <class E> struct csr {
  6. std::vector<int> start;
  7. std::vector<E> elist;
  8. explicit csr(int n, const std::vector<std::pair<int, E>>& edges)
  9. : start(n + 1), elist(edges.size()) {
  10. for (auto e : edges) {
  11. start[e.first + 1]++;
  12. }
  13. for (int i = 1; i <= n; i++) {
  14. start[i] += start[i - 1];
  15. }
  16. auto counter = start;
  17. for (auto e : edges) {
  18. elist[counter[e.first]++] = e.second;
  19. }
  20. }
  21. };
  22. template <class Cap, class Cost>
  23. struct mcf_graph {
  24. public:
  25. mcf_graph() {}
  26. explicit mcf_graph(int n) : _n(n) {}
  27. // 添加一条从 from 到 to,容量为 cap,单位费用为 cost 的边
  28. int add_edge(int from, int to, Cap cap, Cost cost) {
  29. assert(0 <= from && from < _n);
  30. assert(0 <= to && to < _n);
  31. assert(0 <= cap);
  32. assert(0 <= cost);
  33. int m = int(_edges.size());
  34. _edges.push_back({from, to, cap, 0, cost});
  35. return m;
  36. }
  37. struct edge {
  38. int from, to;
  39. Cap cap, flow;
  40. Cost cost;
  41. };
  42. // 获取第 i 条边(按照 add_edge 的顺序)
  43. edge get_edge(int i) {
  44. int m = int(_edges.size());
  45. assert(0 <= i && i < m);
  46. return _edges[i];
  47. }
  48. // 获取所有边
  49. std::vector<edge> edges() { return _edges; }
  50. std::pair<Cap, Cost> flow(int s, int t) {
  51. return flow(s, t, std::numeric_limits<Cap>::max());
  52. }
  53. std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
  54. return slope(s, t, flow_limit).back();
  55. }
  56. std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
  57. return slope(s, t, std::numeric_limits<Cap>::max());
  58. }
  59. std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
  60. assert(0 <= s && s < _n);
  61. assert(0 <= t && t < _n);
  62. assert(s != t);
  63. int m = int(_edges.size());
  64. std::vector<int> edge_idx(m);
  65. auto g = [&]() {
  66. std::vector<int> degree(_n), redge_idx(m);
  67. std::vector<std::pair<int, _edge>> elist;
  68. elist.reserve(2 * m);
  69. for (int i = 0; i < m; i++) {
  70. auto e = _edges[i];
  71. edge_idx[i] = degree[e.from]++;
  72. redge_idx[i] = degree[e.to]++;
  73. elist.push_back({e.from, {e.to, -1, e.cap - e.flow, e.cost}});
  74. elist.push_back({e.to, {e.from, -1, e.flow, -e.cost}});
  75. }
  76. auto _g = csr<_edge>(_n, elist);
  77. for (int i = 0; i < m; i++) {
  78. auto e = _edges[i];
  79. edge_idx[i] += _g.start[e.from];
  80. redge_idx[i] += _g.start[e.to];
  81. _g.elist[edge_idx[i]].rev = redge_idx[i];
  82. _g.elist[redge_idx[i]].rev = edge_idx[i];
  83. }
  84. return _g;
  85. }();
  86. auto result = slope(g, s, t, flow_limit);
  87. for (int i = 0; i < m; i++) {
  88. auto e = g.elist[edge_idx[i]];
  89. _edges[i].flow = _edges[i].cap - e.cap;
  90. }
  91. return result;
  92. }
  93. private:
  94. int _n;
  95. std::vector<edge> _edges;
  96. // inside edge
  97. struct _edge {
  98. int to, rev;
  99. Cap cap;
  100. Cost cost;
  101. };
  102. std::vector<std::pair<Cap, Cost>> slope(csr<_edge>& g, int s, int t, Cap flow_limit) {
  103. // variants (C = maxcost):
  104. // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
  105. // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
  106. // dual_dist[i] = (dual[i], dist[i])
  107. std::vector<std::pair<Cost, Cost>> dual_dist(_n);
  108. std::vector<int> prev_e(_n);
  109. std::vector<bool> vis(_n);
  110. struct Q {
  111. Cost key;
  112. int to;
  113. bool operator<(Q r) const { return key > r.key; }
  114. };
  115. std::vector<int> que_min;
  116. std::vector<Q> que;
  117. auto dual_ref = [&]() {
  118. for (int i = 0; i < _n; i++) {
  119. dual_dist[i].second = std::numeric_limits<Cost>::max();
  120. }
  121. std::fill(vis.begin(), vis.end(), false);
  122. que_min.clear();
  123. que.clear();
  124. // que[0..heap_r) was heapified
  125. size_t heap_r = 0;
  126. dual_dist[s].second = 0;
  127. que_min.push_back(s);
  128. while (!que_min.empty() || !que.empty()) {
  129. int v;
  130. if (!que_min.empty()) {
  131. v = que_min.back();
  132. que_min.pop_back();
  133. } else {
  134. while (heap_r < que.size()) {
  135. heap_r++;
  136. std::push_heap(que.begin(), que.begin() + heap_r);
  137. }
  138. v = que.front().to;
  139. std::pop_heap(que.begin(), que.end());
  140. que.pop_back();
  141. heap_r--;
  142. }
  143. if (vis[v]) continue;
  144. vis[v] = true;
  145. if (v == t) break;
  146. // dist[v] = shortest(s, v) + dual[s] - dual[v]
  147. // dist[v] >= 0 (all reduced cost are positive)
  148. // dist[v] <= (n-1)C
  149. Cost dual_v = dual_dist[v].first, dist_v = dual_dist[v].second;
  150. for (int i = g.start[v]; i < g.start[v + 1]; i++) {
  151. auto e = g.elist[i];
  152. if (!e.cap) continue;
  153. // |-dual[e.to] + dual[v]| <= (n-1)C
  154. // cost <= C - -(n-1)C + 0 = nC
  155. Cost cost = e.cost - dual_dist[e.to].first + dual_v;
  156. if (dual_dist[e.to].second - dist_v > cost) {
  157. Cost dist_to = dist_v + cost;
  158. dual_dist[e.to].second = dist_to;
  159. prev_e[e.to] = e.rev;
  160. if (dist_to == dist_v) {
  161. que_min.push_back(e.to);
  162. } else {
  163. que.push_back(Q{dist_to, e.to});
  164. }
  165. }
  166. }
  167. }
  168. if (!vis[t]) {
  169. return false;
  170. }
  171. for (int v = 0; v < _n; v++) {
  172. if (!vis[v]) continue;
  173. // dual[v] = dual[v] - dist[t] + dist[v]
  174. // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) +
  175. // (shortest(s, v) + dual[s] - dual[v]) = - shortest(s,
  176. // t) + dual[t] + shortest(s, v) = shortest(s, v) -
  177. // shortest(s, t) >= 0 - (n-1)C
  178. dual_dist[v].first -= dual_dist[t].second - dual_dist[v].second;
  179. }
  180. return true;
  181. };
  182. Cap flow = 0;
  183. Cost cost = 0, prev_cost_per_flow = -1;
  184. std::vector<std::pair<Cap, Cost>> result = {{Cap(0), Cost(0)}};
  185. while (flow < flow_limit) {
  186. if (!dual_ref()) break;
  187. Cap c = flow_limit - flow;
  188. for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
  189. c = std::min(c, g.elist[g.elist[prev_e[v]].rev].cap);
  190. }
  191. for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
  192. auto& e = g.elist[prev_e[v]];
  193. e.cap += c;
  194. g.elist[e.rev].cap -= c;
  195. }
  196. Cost d = -dual_dist[s].first;
  197. flow += c;
  198. cost += c * d;
  199. if (prev_cost_per_flow == d) {
  200. result.pop_back();
  201. }
  202. result.push_back({flow, cost});
  203. prev_cost_per_flow = d;
  204. }
  205. return result;
  206. }
  207. };

最大费用流

  1. template <class T> struct simple_queue {
  2. std::vector<T> payload;
  3. int pos = 0;
  4. void reserve(int n) { payload.reserve(n); }
  5. int size() const { return int(payload.size()) - pos; }
  6. bool empty() const { return pos == int(payload.size()); }
  7. void push(const T& t) { payload.push_back(t); }
  8. T& front() { return payload[pos]; }
  9. void clear() {
  10. payload.clear();
  11. pos = 0;
  12. }
  13. void pop() { pos++; }
  14. };
  15. template <class E> struct csr {
  16. std::vector<int> start;
  17. std::vector<E> elist;
  18. explicit csr(int n, const std::vector<std::pair<int, E>>& edges)
  19. : start(n + 1), elist(edges.size()) {
  20. for (auto e : edges) {
  21. start[e.first + 1]++;
  22. }
  23. for (int i = 1; i <= n; i++) {
  24. start[i] += start[i - 1];
  25. }
  26. auto counter = start;
  27. for (auto e : edges) {
  28. elist[counter[e.first]++] = e.second;
  29. }
  30. }
  31. };
  32. template <class Cap, class Cost>
  33. struct mcf_graph {
  34. public:
  35. mcf_graph() {}
  36. explicit mcf_graph(int n) : _n(n) {}
  37. // 添加一条从 from 到 to,容量为 cap,单位费用为 cost 的边
  38. int add_edge(int from, int to, Cap cap, Cost cost) {
  39. assert(0 <= from && from < _n);
  40. assert(0 <= to && to < _n);
  41. assert(0 <= cap);
  42. // assert(0 <= cost);
  43. int m = int(_edges.size());
  44. _edges.push_back({from, to, cap, 0, cost});
  45. return m;
  46. }
  47. struct edge {
  48. int from, to;
  49. Cap cap, flow;
  50. Cost cost;
  51. };
  52. // 获取第 i 条边(按照 add_edge 的顺序)
  53. edge get_edge(int i) {
  54. int m = int(_edges.size());
  55. assert(0 <= i && i < m);
  56. return _edges[i];
  57. }
  58. // 获取所有边
  59. std::vector<edge> edges() { return _edges; }
  60. std::pair<Cap, Cost> flow(int s, int t) {
  61. return flow(s, t, std::numeric_limits<Cap>::max());
  62. }
  63. std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
  64. return slope(s, t, flow_limit).back();
  65. }
  66. std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
  67. return slope(s, t, std::numeric_limits<Cap>::max());
  68. }
  69. std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
  70. assert(0 <= s && s < _n);
  71. assert(0 <= t && t < _n);
  72. assert(s != t);
  73. int m = int(_edges.size());
  74. std::vector<int> edge_idx(m);
  75. auto g = [&]() {
  76. std::vector<int> degree(_n), redge_idx(m);
  77. std::vector<std::pair<int, _edge>> elist;
  78. elist.reserve(2 * m);
  79. for (int i = 0; i < m; i++) {
  80. auto e = _edges[i];
  81. edge_idx[i] = degree[e.from]++;
  82. redge_idx[i] = degree[e.to]++;
  83. elist.push_back({e.from, {e.to, -1, e.cap - e.flow, e.cost}});
  84. elist.push_back({e.to, {e.from, -1, e.flow, -e.cost}});
  85. }
  86. auto _g = csr<_edge>(_n, elist);
  87. for (int i = 0; i < m; i++) {
  88. auto e = _edges[i];
  89. edge_idx[i] += _g.start[e.from];
  90. redge_idx[i] += _g.start[e.to];
  91. _g.elist[edge_idx[i]].rev = redge_idx[i];
  92. _g.elist[redge_idx[i]].rev = edge_idx[i];
  93. }
  94. return _g;
  95. }();
  96. auto result = slope(g, s, t, flow_limit);
  97. for (int i = 0; i < m; i++) {
  98. auto e = g.elist[edge_idx[i]];
  99. _edges[i].flow = _edges[i].cap - e.cap;
  100. }
  101. return result;
  102. }
  103. private:
  104. int _n;
  105. std::vector<edge> _edges;
  106. // inside edge
  107. struct _edge {
  108. int to, rev;
  109. Cap cap;
  110. Cost cost;
  111. };
  112. std::vector<Cost> spfa(csr<_edge>& g, int s, int t) {
  113. std::vector<Cost> dist(_n, std::numeric_limits<Cost>::max() / 2);
  114. std::vector<bool> vis(_n);
  115. simple_queue<int> q;
  116. q.push(s); dist[s] = 0;
  117. while(q.size()) {
  118. int x = q.front(); q.pop();
  119. vis[x] = 0;
  120. for(int i = g.start[x]; i < g.start[x + 1]; i ++) {
  121. auto e = g.elist[i];
  122. int y = e.to;
  123. if(e.cap > 0 && dist[y] - dist[x] > e.cost) {
  124. dist[y] = dist[x] + e.cost;
  125. if(vis[y]) continue;
  126. vis[y] = 1; q.push(y);
  127. }
  128. }
  129. }
  130. return dist;
  131. }
  132. std::vector<std::pair<Cap, Cost>> slope(csr<_edge>& g, int s, int t, Cap flow_limit) {
  133. std::vector<std::pair<Cost, Cost>> dual_dist(_n);
  134. std::vector<int> prev_e(_n);
  135. std::vector<bool> vis(_n);
  136. struct Q {
  137. Cost key;
  138. int to;
  139. bool operator<(Q r) const { return key > r.key; }
  140. };
  141. std::vector<int> que_min;
  142. std::vector<Q> que;
  143. auto h = spfa(g, s, t);
  144. for(int i = 0; i < _n; i++) dual_dist[i].first = h[i];
  145. auto dual_ref = [&]() {
  146. for (int i = 0; i < _n; i++) {
  147. dual_dist[i].second = std::numeric_limits<Cost>::max();
  148. }
  149. std::fill(vis.begin(), vis.end(), false);
  150. que_min.clear();
  151. que.clear();
  152. // que[0..heap_r) was heapified
  153. size_t heap_r = 0;
  154. dual_dist[s].second = 0;
  155. que_min.push_back(s);
  156. while (!que_min.empty() || !que.empty()) {
  157. int v;
  158. if (!que_min.empty()) {
  159. v = que_min.back();
  160. que_min.pop_back();
  161. } else {
  162. while (heap_r < que.size()) {
  163. heap_r++;
  164. std::push_heap(que.begin(), que.begin() + heap_r);
  165. }
  166. v = que.front().to;
  167. std::pop_heap(que.begin(), que.end());
  168. que.pop_back();
  169. heap_r--;
  170. }
  171. if (vis[v]) continue;
  172. vis[v] = true;
  173. Cost dual_v = dual_dist[v].first, dist_v = dual_dist[v].second;
  174. for (int i = g.start[v]; i < g.start[v + 1]; i++) {
  175. auto e = g.elist[i];
  176. if (!e.cap) continue;
  177. // |-dual[e.to] + dual[v]| <= (n-1)C
  178. // cost <= C - -(n-1)C + 0 = nC
  179. Cost cost = e.cost - dual_dist[e.to].first + dual_v;
  180. if (dual_dist[e.to].second - dist_v > cost) {
  181. Cost dist_to = dist_v + cost;
  182. assert(dist_to >= 0);
  183. dual_dist[e.to].second = dist_to;
  184. prev_e[e.to] = e.rev;
  185. if (dist_to == dist_v) {
  186. que_min.push_back(e.to);
  187. } else {
  188. que.push_back(Q{dist_to, e.to});
  189. }
  190. }
  191. }
  192. }
  193. if (!vis[t]) {
  194. return false;
  195. }
  196. for (int v = 0; v < _n; v++) {
  197. dual_dist[v].first += dual_dist[v].second;
  198. }
  199. return true;
  200. };
  201. Cap flow = 0;
  202. Cost cost = 0, prev_cost_per_flow = -1;
  203. std::vector<std::pair<Cap, Cost>> result = {{Cap(0), Cost(0)}};
  204. while (flow < flow_limit) {
  205. if (!dual_ref()) break;
  206. Cap c = flow_limit - flow;
  207. for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
  208. c = std::min(c, g.elist[g.elist[prev_e[v]].rev].cap);
  209. }
  210. for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
  211. auto& e = g.elist[prev_e[v]];
  212. e.cap += c;
  213. g.elist[e.rev].cap -= c;
  214. }
  215. Cost d = dual_dist[t].first;
  216. flow += c;
  217. cost += c * d;
  218. if (prev_cost_per_flow == d) {
  219. result.pop_back();
  220. }
  221. result.push_back({flow, cost});
  222. prev_cost_per_flow = d;
  223. }
  224. return result;
  225. }
  226. };