qwerty787788

MinCostMaxFlow (PriorityQueue)

Oct 11th, 2020 (edited)
2,246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.44 KB | None | 0 0
  1.     class MinCostMaxFlowGraph {
  2.         int n;
  3.         ArrayList<Edge>[] g;
  4.  
  5.         class Edge {
  6.             int from, to;
  7.             long cap, flow, cost;
  8.             Edge rev;
  9.  
  10.             public Edge(int from, int to, long cap, long flow, long cost) {
  11.                 super();
  12.                 this.from = from;
  13.                 this.to = to;
  14.                 this.cap = cap;
  15.                 this.flow = flow;
  16.                 this.cost = cost;
  17.             }
  18.         }
  19.  
  20.         class Vertex implements Comparable<Vertex> {
  21.             final int v;
  22.             final Edge e;
  23.             final long d;
  24.  
  25.             public Vertex(int v, Edge e, long d) {
  26.                 super();
  27.                 this.v = v;
  28.                 this.e = e;
  29.                 this.d = d;
  30.             }
  31.  
  32.             @Override
  33.             public int compareTo(Vertex o) {
  34.                 return d < o.d ? -1 : d > o.d ? 1 : v - o.v;
  35.             }
  36.  
  37.         }
  38.  
  39.         public MinCostMaxFlowGraph(int n) {
  40.             super();
  41.             this.n = n;
  42.             g = new ArrayList[n];
  43.             for (int i = 0; i < n; i++)
  44.                 g[i] = new ArrayList<Edge>();
  45.         }
  46.  
  47.         public void addEdge(int fr, int to, int cap, long cost) {
  48.             Edge e1 = new Edge(fr, to, cap, 0, cost);
  49.             Edge e2 = new Edge(to, fr, 0, 0, -cost);
  50.             e1.rev = e2;
  51.             e2.rev = e1;
  52.             g[fr].add(e1);
  53.             g[to].add(e2);
  54.         }
  55.  
  56.         public long[] getMinCostMaxFlow(int source, int target) {
  57.             long[] h = new long[n];
  58.             for (boolean changed = true; changed; ) {
  59.                 changed = false;
  60.                 for (int i = 0; i < n; i++) {
  61.                     for (Edge e : g[i]) {
  62.                         if (e.cap > 0 && h[e.to] > h[e.from] + e.cost) {
  63.                             h[e.to] = h[e.from] + e.cost;
  64.                             changed = true;
  65.                         }
  66.                     }
  67.                 }
  68.             }
  69.             Vertex[] vertices = new Vertex[n];
  70.             long[] d = new long[n];
  71.             boolean[] was = new boolean[n];
  72.             int flow = 0;
  73.             long cost = 0;
  74.             while (true) {
  75.                 Arrays.fill(was, false);
  76.                 dijkstra(source, vertices, d, h, was);
  77.                 if (d[target] == Long.MAX_VALUE) {
  78.                     break;
  79.                 }
  80.                 long addFlow = Long.MAX_VALUE;
  81.                 Vertex v = vertices[target];
  82.                 while (v != vertices[source]) {
  83.                     addFlow = Math.min(addFlow, v.e.cap - v.e.flow);
  84.                     v = vertices[v.e.from];
  85.                 }
  86.                 cost += (d[target] + h[target] - h[source]) * addFlow;
  87.                 flow += addFlow;
  88.                 v = vertices[target];
  89.                 while (v != vertices[source]) {
  90.                     v.e.flow += addFlow;
  91.                     v.e.rev.flow -= addFlow;
  92.                     v = vertices[v.e.from];
  93.                 }
  94.                 for (int i = 0; i < n; i++) {
  95.                     h[i] += d[i] == Long.MAX_VALUE ? 0 : d[i];
  96.                 }
  97.             }
  98.             return new long[]{flow, cost};
  99.         }
  100.  
  101.         void dijkstra(int source, Vertex[] vertices, long[] d, long[] h, boolean[] was) {
  102.             PriorityQueue<Vertex> ts = new PriorityQueue<Vertex>(vertices.length);
  103.             Arrays.fill(d, Long.MAX_VALUE);
  104.             d[source] = 0;
  105.             vertices[source] = new Vertex(source, null, 0);
  106.             ts.add(vertices[source]);
  107.             while (!ts.isEmpty()) {
  108.                 Vertex v = ts.poll();
  109.                 if (was[v.v]) {
  110.                     continue;
  111.                 }
  112.                 was[v.v] = true;
  113.                 for (Edge e : g[v.v]) {
  114.                     if (e.flow >= e.cap) {
  115.                         continue;
  116.                     }
  117.                     if (d[e.to] == Long.MAX_VALUE
  118.                             || d[e.to] > d[e.from] + e.cost + h[e.from]
  119.                             - h[e.to]) {
  120.                         if (e.cost + h[e.from] - h[e.to] < 0) {
  121.                             throw new AssertionError();
  122.                         }
  123.                         d[e.to] = d[e.from] + e.cost + h[e.from] - h[e.to];
  124.                         vertices[e.to] = new Vertex(e.to, e, d[e.to]);
  125.                         ts.add(vertices[e.to]);
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.     }
Advertisement
Add Comment
Please, Sign In to add comment