diff --git a/src/main/java/com/thealgorithms/graph/Dinic.java b/src/main/java/com/thealgorithms/graph/Dinic.java index c45bd62ddfbb..f327dc6720fa 100644 --- a/src/main/java/com/thealgorithms/graph/Dinic.java +++ b/src/main/java/com/thealgorithms/graph/Dinic.java @@ -5,40 +5,54 @@ import java.util.Queue; /** - * Dinic's algorithm for computing maximum flow in a directed graph. + * Implementation of Dinic's Algorithm to compute the maximum flow + * in a directed graph. * - *
Time complexity: O(E * V^2) in the worst case, but typically faster in practice - * and near O(E * sqrt(V)) for unit networks.
+ *Algorithm idea: + * The algorithm works by repeatedly building a level graph using BFS + * and then finding blocking flows using DFS until no more augmenting + * paths exist.
* - *The graph is represented using a capacity matrix where capacity[u][v] is the - * capacity of the directed edge u -> v. Capacities must be non-negative. - * The algorithm builds level graphs using BFS and finds blocking flows using DFS - * with current-edge optimization.
+ *Time Complexity:
+ * Worst case: O(E × V²)
+ * Practical performance: Much faster, often close to O(E × √V)
This implementation mirrors the API and validation style of + *
The graph is represented using a capacity matrix where + * {@code capacity[u][v]} denotes the capacity of the directed edge + * from vertex {@code u} to vertex {@code v}.
+ * + *This implementation follows the same validation style as * {@link EdmondsKarp#maxFlow(int[][], int, int)} for consistency.
* - * @see Wikipedia: Dinic's algorithm + * @see + * Wikipedia: Dinic's Algorithm */ public final class Dinic { + + // Private constructor to prevent instantiation private Dinic() { } /** - * Computes the maximum flow from source to sink using Dinic's algorithm. + * Computes the maximum flow from a source vertex to a sink vertex + * using Dinic's Algorithm. * - * @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 the input matrix is null/non-square/has negatives or - * indices invalid + * @param capacity square matrix representing edge capacities + * @param source index of the source vertex + * @param sink index of the sink vertex + * @return maximum possible flow from source to sink + * @throws IllegalArgumentException if the input matrix is invalid */ public static int maxFlow(int[][] capacity, int source, int sink) { + + // Validate capacity matrix if (capacity == null || capacity.length == 0) { throw new IllegalArgumentException("Capacity matrix must not be null or empty"); } + final int n = capacity.length; + + // Ensure matrix is square and capacities are non-negative for (int i = 0; i < n; i++) { if (capacity[i] == null || capacity[i].length != n) { throw new IllegalArgumentException("Capacity matrix must be square"); @@ -49,69 +63,87 @@ public static int maxFlow(int[][] capacity, int source, int sink) { } } } + + // Validate source and sink if (source < 0 || sink < 0 || source >= n || sink >= n) { throw new IllegalArgumentException("Source and sink must be valid vertex indices"); } + if (source == sink) { return 0; } - // residual capacities + // Create residual graph int[][] residual = new int[n][n]; for (int i = 0; i < n; i++) { residual[i] = Arrays.copyOf(capacity[i], n); } int[] level = new int[n]; - int flow = 0; + int maxFlow = 0; + + // Repeatedly build level graph and find blocking flows while (bfsBuildLevelGraph(residual, source, sink, level)) { int[] next = new int[n]; // current-edge optimization - int pushed; - do { - pushed = dfsBlocking(residual, level, next, source, sink, Integer.MAX_VALUE); - flow += pushed; - } while (pushed > 0); + int flow; + + // Push flow while augmenting paths exist + while ((flow = dfsBlocking(residual, level, next, source, sink, Integer.MAX_VALUE)) > 0) { + maxFlow += flow; + } } - return flow; + return maxFlow; } + /** + * Builds the level graph using BFS. + */ private static boolean bfsBuildLevelGraph(int[][] residual, int source, int sink, int[] level) { Arrays.fill(level, -1); level[source] = 0; - Queue