Files
Java/src/main/java/com/thealgorithms/graph/EdmondsKarp.java
Sivasuthan Sukumar f8f315eaa8 Extend Graph Algorithms: Added Two Popular Algorithms: BronKerbosch, EdmondsKarp (#6576)
* Bron–Kerbosch algorithm added.

* test:Bron–Kerbosch algorithm added.

* lint checked.

* clang-format linting checked.

* lint checked in remote

Removed duplicate import statements for assertions.

* Remove unnecessary blank line in BronKerboschTest

* EdmondsKarp algorithm added.

* reformatted

---------

Co-authored-by: Oleksandr Klymenko <alexanderklmn@gmail.com>
2025-10-01 21:44:43 +02:00

108 lines
3.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.thealgorithms.graph;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
/**
* Implementation of the EdmondsKarp algorithm for computing the maximum flow of a directed graph.
* <p>
* The algorithm runs in O(V * E^2) time and is a specific implementation of the FordFulkerson
* method where the augmenting paths are found using breadth-first search (BFS) to ensure the
* shortest augmenting paths (in terms of the number of edges) are used.
* </p>
*
* <p>The graph is represented with a capacity matrix where {@code capacity[u][v]} denotes the
* capacity of the edge from {@code u} to {@code v}. Negative capacities are not allowed.</p>
*
* @author <a href="https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm">Wikipedia: EdmondsKarp algorithm</a>
*/
public final class EdmondsKarp {
private EdmondsKarp() {
}
/**
* Computes the maximum flow from {@code source} to {@code sink} in the provided capacity matrix.
*
* @param capacity the capacity matrix representing the directed graph; must be square and non-null
* @param source the source vertex index
* @param sink the sink vertex index
* @return the value of the maximum flow between {@code source} and {@code sink}
* @throws IllegalArgumentException if the matrix is {@code null}, not square, contains negative
* capacities, or if {@code source} / {@code sink} indices are invalid
*/
public static int maxFlow(int[][] capacity, int source, int sink) {
if (capacity == null || capacity.length == 0) {
throw new IllegalArgumentException("Capacity matrix must not be null or empty");
}
final int n = capacity.length;
for (int row = 0; row < n; row++) {
if (capacity[row] == null || capacity[row].length != n) {
throw new IllegalArgumentException("Capacity matrix must be square");
}
for (int col = 0; col < n; col++) {
if (capacity[row][col] < 0) {
throw new IllegalArgumentException("Capacities must be non-negative");
}
}
}
if (source < 0 || source >= n || sink < 0 || sink >= n) {
throw new IllegalArgumentException("Source and sink must be valid vertex indices");
}
if (source == sink) {
return 0;
}
final int[][] residual = new int[n][n];
for (int i = 0; i < n; i++) {
residual[i] = Arrays.copyOf(capacity[i], n);
}
final int[] parent = new int[n];
int maxFlow = 0;
while (bfs(residual, source, sink, parent)) {
int pathFlow = Integer.MAX_VALUE;
for (int v = sink; v != source; v = parent[v]) {
int u = parent[v];
pathFlow = Math.min(pathFlow, residual[u][v]);
}
for (int v = sink; v != source; v = parent[v]) {
int u = parent[v];
residual[u][v] -= pathFlow;
residual[v][u] += pathFlow;
}
maxFlow += pathFlow;
}
return maxFlow;
}
private static boolean bfs(int[][] residual, int source, int sink, int[] parent) {
Arrays.fill(parent, -1);
parent[source] = source;
Queue<Integer> queue = new ArrayDeque<>();
queue.add(source);
while (!queue.isEmpty()) {
int u = queue.poll();
for (int v = 0; v < residual.length; v++) {
if (residual[u][v] > 0 && parent[v] == -1) {
parent[v] = u;
if (v == sink) {
return true;
}
queue.add(v);
}
}
}
return false;
}
}