Dinic.cc 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Adjacency list implementation of Dinic's blocking flow algorithm.
  2. // This is very fast in practice, and only loses to push-relabel flow.
  3. //
  4. // Running time:
  5. // O(|V|^2 |E|)
  6. //
  7. // INPUT:
  8. // - graph, constructed using AddEdge()
  9. // - source
  10. // - sink
  11. //
  12. // OUTPUT:
  13. // - maximum flow value
  14. // - To obtain the actual flow values, look at all edges with
  15. // capacity > 0 (zero capacity edges are residual edges).
  16. #include <cmath>
  17. #include <vector>
  18. #include <iostream>
  19. #include <queue>
  20. using namespace std;
  21. const int INF = 2000000000;
  22. struct Edge {
  23. int from, to, cap, flow, index;
  24. Edge(int from, int to, int cap, int flow, int index) :
  25. from(from), to(to), cap(cap), flow(flow), index(index) {}
  26. };
  27. struct Dinic {
  28. int N;
  29. vector<vector<Edge> > G;
  30. vector<Edge *> dad;
  31. vector<int> Q;
  32. Dinic(int N) : N(N), G(N), dad(N), Q(N) {}
  33. void AddEdge(int from, int to, int cap) {
  34. G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
  35. if (from == to) G[from].back().index++;
  36. G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
  37. }
  38. long long BlockingFlow(int s, int t) {
  39. fill(dad.begin(), dad.end(), (Edge *) NULL);
  40. dad[s] = &G[0][0] - 1;
  41. int head = 0, tail = 0;
  42. Q[tail++] = s;
  43. while (head < tail) {
  44. int x = Q[head++];
  45. for (int i = 0; i < G[x].size(); i++) {
  46. Edge &e = G[x][i];
  47. if (!dad[e.to] && e.cap - e.flow > 0) {
  48. dad[e.to] = &G[x][i];
  49. Q[tail++] = e.to;
  50. }
  51. }
  52. }
  53. if (!dad[t]) return 0;
  54. long long totflow = 0;
  55. for (int i = 0; i < G[t].size(); i++) {
  56. Edge *start = &G[G[t][i].to][G[t][i].index];
  57. int amt = INF;
  58. for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
  59. if (!e) { amt = 0; break; }
  60. amt = min(amt, e->cap - e->flow);
  61. }
  62. if (amt == 0) continue;
  63. for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
  64. e->flow += amt;
  65. G[e->to][e->index].flow -= amt;
  66. }
  67. totflow += amt;
  68. }
  69. return totflow;
  70. }
  71. long long GetMaxFlow(int s, int t) {
  72. long long totflow = 0;
  73. while (long long flow = BlockingFlow(s, t))
  74. totflow += flow;
  75. return totflow;
  76. }
  77. };