Advertisement
qwerty787788

Fast Flow

Feb 19th, 2015
1,000
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 3.00 KB | None | 0 0
  1.  
  2.     class Edge {
  3.         int fr, to;
  4.         long flow, cap;
  5.         Edge rev;
  6.  
  7.         Edge(int fr, int to, long cap) {
  8.             this.fr = fr;
  9.             this.to = to;
  10.             this.cap = cap;
  11.         }
  12.     }
  13.  
  14.     class Flow {
  15.         int n;
  16.         int[] q;
  17.         int[] dist;
  18.         int[] cntOnLayer;
  19.         int[] prev;
  20.         int[] curEdge;
  21.         boolean[] was;
  22.         boolean canReachSink;
  23.         Edge[] prevEdge;
  24.         List<Edge>[] g;
  25.  
  26.         Flow(int n) {
  27.             this.n = n;
  28.             g = new ArrayList[n];
  29.             for (int i = 0; i < n; i++) {
  30.                 g[i] = new ArrayList<>();
  31.             }
  32.             q = new int[n];
  33.             was = new boolean[n];
  34.             dist = new int[n];
  35.             cntOnLayer = new int[n + 1];
  36.             prev = new int[n];
  37.             curEdge = new int[n];
  38.             prevEdge = new Edge[n];
  39.         }
  40.  
  41.         Edge addEdge(int fr, int to, long cap) {
  42.             Edge e1 = new Edge(fr, to, cap);
  43.             Edge e2 = new Edge(to, fr, 0);
  44.             e1.rev = e2;
  45.             e2.rev = e1;
  46.             g[fr].add(e1);
  47.             g[to].add(e2);
  48.             return e1;
  49.         }
  50.  
  51.         boolean bfs() {
  52.             Arrays.fill(was, false);
  53.             Arrays.fill(dist, n);
  54.             Arrays.fill(cntOnLayer, 0);
  55.             cntOnLayer[n] = n;
  56.             dist[n - 1] = 0;
  57.             was[n - 1] = true;
  58.             cntOnLayer[0]++;
  59.             cntOnLayer[n]--;
  60.             int qIt = 0, qSz = 0;
  61.             q[qSz++] = n - 1;
  62.             while (qIt < qSz) {
  63.                 int v = q[qIt++];
  64.                 for (Edge e : g[v]) {
  65.                     if (was[e.to] || e.rev.flow == e.rev.cap) {
  66.                         continue;
  67.                     }
  68.                     was[e.to] = true;
  69.                     q[qSz] = e.to;
  70.                     cntOnLayer[dist[e.to]]--;
  71.                     dist[e.to] = dist[v] + 1;
  72.                     cntOnLayer[dist[e.to]]++;
  73.                     qSz++;
  74.                 }
  75.             }
  76.             return dist[0] != n;
  77.         }
  78.  
  79.         long augment() {
  80.             long flow = Long.MAX_VALUE;
  81.             for (int i = n - 1; i != 0; i = prev[i]) {
  82.                 flow = Math.min(flow, prevEdge[i].cap - prevEdge[i].flow);
  83.             }
  84.             for (int i = n - 1; i != 0; i = prev[i]) {
  85.                 prevEdge[i].flow += flow;
  86.                 prevEdge[i].rev.flow -= flow;
  87.             }
  88.             return flow;
  89.         }
  90.  
  91.         int retreat(int v) {
  92.             int newDist = n - 1;
  93.             for (Edge e : g[v]) {
  94.                 if (e.flow < e.cap && dist[e.to] < newDist) {
  95.                     newDist = dist[e.to];
  96.                 }
  97.             }
  98.             cntOnLayer[dist[v]]--;
  99.             if (cntOnLayer[dist[v]] == 0) {
  100.                 if (newDist + 1 > dist[v]) {
  101.                     canReachSink = false;
  102.                 }
  103.             }
  104.             dist[v] = 1 + newDist;
  105.             cntOnLayer[dist[v]]++;
  106.             if (v != 0) {
  107.                 v = prev[v];
  108.             }
  109.             return v;
  110.         }
  111.  
  112.         void clear() {
  113.             for (int v = 0; v < n; v++) {
  114.                 for (Edge e : g[v]) {
  115.                     e.flow = 0;
  116.                 }
  117.             }
  118.         }
  119.  
  120.         long flow() {
  121.             long res = 0;
  122.             canReachSink = true;
  123.             Arrays.fill(prev, 0);
  124.             Arrays.fill(curEdge, 0);
  125.             clear();
  126.             if (!bfs()) {
  127.                 return 0;
  128.             }
  129.             int v = 0;
  130.             while (dist[0] < n) {
  131.                 for (; curEdge[v] < g[v].size(); curEdge[v]++) {
  132.                     Edge e = g[v].get(curEdge[v]);
  133.                     if (e.flow < e.cap && dist[v] == dist[e.to] + 1)
  134.                         break;
  135.                 }
  136.                 if (curEdge[v] != g[v].size()) {
  137.                     Edge e = g[v].get(curEdge[v]);
  138.                     prev[e.to] = v;
  139.                     prevEdge[e.to] = e;
  140.                     v = e.to;
  141.                     if (v == n - 1) {
  142.                         res += augment();
  143.                         v = 0;
  144.                     }
  145.                 } else {
  146.                     curEdge[v] = 0;
  147.                     v = retreat(v);
  148.                     if (!canReachSink) {
  149.                         break;
  150.                     }
  151.                 }
  152.             }
  153.             return res;
  154.         }
  155.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement