package com.thealgorithms.graph; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Queue; /** * Push–Relabel (Relabel-to-Front variant simplified to array scanning) for maximum flow. * *
Input graph is a capacity matrix where {@code capacity[u][v]} is the capacity of the edge * {@code u -> v}. Capacities must be non-negative. Vertices are indexed in {@code [0, n)}. * *
Time complexity: O(V^3) in the worst case for the array-based variant; typically fast in * practice. This implementation uses a residual network over an adjacency-matrix representation. * *
The API mirrors {@link EdmondsKarp#maxFlow(int[][], int, int)} and {@link Dinic#maxFlow(int[][], int, int)}.
*
* @see Wikipedia: Push–Relabel maximum flow algorithm
*/
public final class PushRelabel {
private PushRelabel() {
}
/**
* Computes the maximum flow from {@code source} to {@code sink} using Push–Relabel.
*
* @param capacity square capacity matrix (n x n); entries must be >= 0
* @param source source vertex index in [0, n)
* @param sink sink vertex index in [0, n)
* @return the maximum flow value
* @throws IllegalArgumentException if inputs are invalid
*/
public static int maxFlow(int[][] capacity, int source, int sink) {
validate(capacity, source, sink);
final int n = capacity.length;
if (source == sink) {
return 0;
}
int[][] residual = new int[n][n];
for (int i = 0; i < n; i++) {
residual[i] = Arrays.copyOf(capacity[i], n);
}
int[] height = new int[n];
int[] excess = new int[n];
int[] nextNeighbor = new int[n];
// Preflow initialization
height[source] = n;
for (int v = 0; v < n; v++) {
int cap = residual[source][v];
if (cap > 0) {
residual[source][v] -= cap;
residual[v][source] += cap;
excess[v] += cap;
excess[source] -= cap;
}
}
// Active queue contains vertices (except source/sink) with positive excess
Queue