qwerty787788

MinCostMaxFlow (PriorityQueue without objects)

Oct 11th, 2020 (edited)
3,295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.36 KB | None | 0 0
  1. class VertexPriorityQueue {
  2.         long[] dist;
  3.         int[] posInHeap;
  4.         int[] heap;
  5.         int heapSize;
  6.  
  7.         VertexPriorityQueue(int n) {
  8.             dist = new long[n];
  9.             Arrays.fill(dist, Long.MAX_VALUE);
  10.             posInHeap = new int[n];
  11.             Arrays.fill(posInHeap, -1);
  12.             heap = new int[n];
  13.             heapSize = 0;
  14.         }
  15.  
  16.         void clear() {
  17.             while (heapSize > 0) {
  18.                 removeFromHeap(heap[heapSize - 1]);
  19.                 heapSize--;
  20.             }
  21.         }
  22.  
  23.         void removeFromHeap(int vertex) {
  24.             int pos = posInHeap[vertex];
  25.             if (pos == -1) {
  26.                 return;
  27.             }
  28.             heapSize--;
  29.             if (pos < heapSize) {
  30.                 swap(pos, heapSize);
  31.                 int lastPos = siftUp(pos);
  32.                 siftDown(lastPos);
  33.             }
  34.             dist[vertex] = Long.MAX_VALUE;
  35.             posInHeap[vertex] = -1;
  36.             if (heapSize < 0) {
  37.                 throw new AssertionError();
  38.             }
  39.         }
  40.  
  41.         void set(int vertex, int pos) {
  42.             posInHeap[vertex] = pos;
  43.             heap[pos] = vertex;
  44.         }
  45.  
  46.         void swap(int p1, int p2) {
  47.             int v1 = heap[p1];
  48.             int v2 = heap[p2];
  49.             set(v1, p2);
  50.             set(v2, p1);
  51.         }
  52.  
  53.         void siftDown(int pos) {
  54.             while (pos > 0) {
  55.                 int parentPos = (pos - 1) >>> 1;
  56.                 if (dist[heap[parentPos]] <= dist[heap[pos]]) {
  57.                     break;
  58.                 }
  59.                 swap(pos, parentPos);
  60.                 pos = parentPos;
  61.             }
  62.         }
  63.  
  64.         int siftUp(int pos) {
  65.             while (true) {
  66.                 int ch1 = pos * 2 + 1, ch2 = pos * 2 + 2;
  67.                 if (ch1 >= heapSize) {
  68.                     break;
  69.                 }
  70.                 int minChildPos = ch2 >= heapSize ? ch1 : (dist[heap[ch1]] < dist[heap[ch2]] ? ch1 : ch2);
  71.                 if (dist[heap[pos]] < dist[heap[minChildPos]]) {
  72.                     break;
  73.                 }
  74.                 swap(pos, minChildPos);
  75.                 pos = minChildPos;
  76.             }
  77.             return pos;
  78.         }
  79.  
  80.         void add(int vertex, long d) {
  81.             if (d >= dist[vertex]) {
  82.                 throw new AssertionError();
  83.             }
  84.             removeFromHeap(vertex);
  85.             dist[vertex] = d;
  86.             set(vertex, heapSize++);
  87.             siftDown(heapSize - 1);
  88.         }
  89.  
  90.         int poll() {
  91.             if (heapSize == 0) {
  92.                 throw new AssertionError();
  93.             }
  94.             int resVertex = heap[0];
  95.             removeFromHeap(resVertex);
  96.             return resVertex;
  97.         }
  98.  
  99.         boolean isEmpty() {
  100.             return heapSize == 0;
  101.         }
  102.     }
  103.  
  104.     class MinCostMaxFlowGraph {
  105.         int n;
  106.         int totEdges;
  107.         int[] edgeFrom, edgeTo;
  108.         long[] edgeCap, edgeFlow, edgeCost;
  109.         int[] edgeRev;
  110.         int[][] g;
  111.  
  112.  
  113.         int newEdge(int from, int to, long cap, long flow, long cost) {
  114.             edgeFrom[totEdges] = from;
  115.             edgeTo[totEdges] = to;
  116.             edgeCap[totEdges] = cap;
  117.             edgeFlow[totEdges] = flow;
  118.             edgeCost[totEdges] = cost;
  119.             totEdges++;
  120.             return totEdges - 1;
  121.         }
  122.  
  123.         public MinCostMaxFlowGraph(int n, int maxEdges) {
  124.             maxEdges *= 2;
  125.             this.n = n;
  126.             totEdges = 0;
  127.             edgeFrom = new int[maxEdges];
  128.             edgeTo = new int[maxEdges];
  129.             edgeCap = new long[maxEdges];
  130.             edgeFlow = new long[maxEdges];
  131.             edgeCost = new long[maxEdges];
  132.             edgeRev = new int[maxEdges];
  133.         }
  134.  
  135.         public void addEdge(int fr, int to, int cap, long cost) {
  136.             int e1 = newEdge(fr, to, cap, 0, cost);
  137.             int e2 = newEdge(to, fr, 0, 0, -cost);
  138.             edgeRev[e1] = e2;
  139.             edgeRev[e2] = e1;
  140.         }
  141.  
  142.         void buildAllEdges() {
  143.             int[] edgesNum = new int[n];
  144.             for (int eId = 0; eId < totEdges; eId++) {
  145.                 edgesNum[edgeFrom[eId]]++;
  146.             }
  147.             g = new int[n][];
  148.             for (int i =0 ; i < n; i++) {
  149.                 g[i] = new int[edgesNum[i]];
  150.             }
  151.             for (int eId = 0; eId < totEdges; eId++) {
  152.                 g[edgeFrom[eId]][--edgesNum[edgeFrom[eId]]] = eId;
  153.             }
  154.         }
  155.  
  156.         public long[] getMinCostMaxFlow(int source, int target) {
  157.             buildAllEdges();
  158.             long[] h = new long[n];
  159.             for (boolean changed = true; changed; ) {
  160.                 changed = false;
  161.                 for (int i = 0; i < n; i++) {
  162.                     for (int eId : g[i]) {
  163.                         if (edgeCap[eId] > 0 && h[edgeTo[eId]] > h[edgeFrom[eId]] + edgeCost[eId]) {
  164.                             h[edgeTo[eId]] = h[edgeFrom[eId]] + edgeCost[eId];
  165.                             changed = true;
  166.                         }
  167.                     }
  168.                 }
  169.             }
  170.             long[] d = new long[n];
  171.             int[] prevEdge = new int[n];
  172.             VertexPriorityQueue pq = new VertexPriorityQueue(d.length);
  173.             int flow = 0;
  174.             long cost = 0;
  175.             while (true) {
  176.                 pq.clear();
  177.                 dijkstra(source, d, h, prevEdge, pq);
  178.                 if (d[target] == Long.MAX_VALUE) {
  179.                     break;
  180.                 }
  181.                 long addFlow = Long.MAX_VALUE;
  182.                 int v = target;
  183.                 while (v != source) {
  184.                     int e = prevEdge[v];
  185.                     addFlow = Math.min(addFlow, edgeCap[e] - edgeFlow[e]);
  186.                     v = edgeFrom[e];
  187.                 }
  188.                 cost += (d[target] + h[target] - h[source]) * addFlow;
  189.                 flow += addFlow;
  190.                 v = target;
  191.                 while (v != source) {
  192.                     int e = prevEdge[v];
  193.                     edgeFlow[e] += addFlow;
  194.                     edgeFlow[edgeRev[e]] -= addFlow;
  195.                     v = edgeFrom[e];
  196.                 }
  197.                 for (int i = 0; i < n; i++) {
  198.                     h[i] += d[i] == Long.MAX_VALUE ? 0 : d[i];
  199.                 }
  200.             }
  201.             return new long[]{flow, cost};
  202.         }
  203.  
  204.         void dijkstra(int source, long[] d, long[] h, int[] prevEdge, VertexPriorityQueue pq) {
  205.             Arrays.fill(d, Long.MAX_VALUE);
  206.             d[source] = 0;
  207.             pq.add(source, 0);
  208.             while (!pq.isEmpty()) {
  209.                 int v = pq.poll();
  210.                 for (int e : g[v]) {
  211.                     if (edgeFlow[e] >= edgeCap[e]) {
  212.                         continue;
  213.                     }
  214.                     if (d[edgeTo[e]] == Long.MAX_VALUE
  215.                             || d[edgeTo[e]] > d[edgeFrom[e]] + edgeCost[e] + h[edgeFrom[e]]
  216.                             - h[edgeTo[e]]) {
  217.                         if (edgeCost[e] + h[edgeFrom[e]] - h[edgeTo[e]] < 0) {
  218.                             throw new AssertionError();
  219.                         }
  220.                         d[edgeTo[e]] = d[edgeFrom[e]] + edgeCost[e] + h[edgeFrom[e]] - h[edgeTo[e]];
  221.                         prevEdge[edgeTo[e]] = e;
  222.                         pq.add(edgeTo[e], d[edgeTo[e]]);
  223.                     }
  224.                 }
  225.             }
  226.         }
  227.     }
Advertisement
Add Comment
Please, Sign In to add comment