Skip to content

Add Edmond's algorithm for maximum flow #328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions Data Structures/Graphs/EdmondsKarpMaxFlow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import java.util.ArrayDeque;
import java.util.Queue;

/**
* This implementation of Edmonds-Karp algorithms returns the maximum flow in a
* Flow Network. It makes use of the Ford-Fulkerson method.
*
* @author Lukas Keul
* @author Florian Mercks
*/
public class EdmondsKarpMaxFlow {

private long[][] edgeCapacity;
private int[] parentNode;
private boolean[] visitedNode;
private long[][] maxFlowBetweenNodes;

@SuppressWarnings("unused")
private int numOfN, numOfE;

public EdmondsKarpMaxFlow(int numberOfNodes, int numberOfEdges) {
this.numOfN = numberOfNodes;
this.numOfE = numberOfEdges;
this.parentNode = new int[numOfN];
this.visitedNode = new boolean[numOfN];
this.edgeCapacity = new long[numOfN][numOfN];
this.maxFlowBetweenNodes = new long[numOfN][numOfN];
}

/**
* Returns the maximum Flow in a Flow Network
*
* @param flowSource
* represents the starting point of a maximum flow measurement in
* a flow network
* @param FlowTarget
* represents the end point of a maximum flow measurement in a
* flow network
* @return maximum flow in the considered flow network
*/
public long getMaxFlow(int flowSource, int flowTarget) {
while (true) {
final Queue<Integer> flowSourceQueue = new ArrayDeque<Integer>();
flowSourceQueue.add(flowSource);

// iterate through unvisited flowsources
for (int i = 0; i < this.numOfN; ++i)
visitedNode[i] = false;
visitedNode[flowSource] = true;

boolean isFlowSourceChecked = false;
int currentFlowSource;

// iterate throught the flowSourceQueue
while (!flowSourceQueue.isEmpty()) {
// give out the last Element of the Queue
currentFlowSource = flowSourceQueue.peek();

// if the currentFlowSource is the flowTarget, we are done
// iterating
if (currentFlowSource == flowTarget) {
isFlowSourceChecked = true;
break;
}

// remove last element from flowSourceQueue
flowSourceQueue.remove();

// iterate through the number of nodes to check capacity size
for (int i = 0; i < numOfN; ++i) {
// if capacity is greater than the expected flow
// then add the node to the flowSourceQueue
if (!visitedNode[i]
&& edgeCapacity[currentFlowSource][i] > maxFlowBetweenNodes[currentFlowSource][i]) {

visitedNode[i] = true;
flowSourceQueue.add(i);
parentNode[i] = currentFlowSource;
}
}
}
if (isFlowSourceChecked == false)
break;

// subtract the maximum flow between the nodes from the edge
// capacity
long holdPartialResults = edgeCapacity[parentNode[flowTarget]][flowTarget]
- maxFlowBetweenNodes[parentNode[flowTarget]][flowTarget];

// do a breadth first search from target to source to find minimum
// needed capacity
for (int i = flowTarget; i != flowSource; i = parentNode[i])
holdPartialResults = Math.min(holdPartialResults,
(edgeCapacity[parentNode[i]][i] - maxFlowBetweenNodes[parentNode[i]][i]));

// add all minimum needed capacities to the maximum flow between the
// source and the target node
for (int i = flowTarget; i != flowSource; i = parentNode[i]) {
maxFlowBetweenNodes[parentNode[i]][i] += holdPartialResults;
maxFlowBetweenNodes[i][parentNode[i]] -= holdPartialResults;
}
}

long result = 0;

// return the resulting maximum flow between the flowSource and the
// flowTarget
for (int i = 0; i < numOfN; ++i)
result += maxFlowBetweenNodes[flowSource][i];
return result;
}

/**
* Adds an Edge to the flow network
*
* @param fromNode
* is the starting node of an edge
* @param toNode
* is the ending node of an edge
* @param edgeCapacity
* represents edge capacity used for the capacity function which
* calculates the flow
*/
public void addEdge(int fromNode, int toNode, long edgeCapacity) {
assert edgeCapacity >= 0;
this.edgeCapacity[fromNode][toNode] += edgeCapacity;
}

/**
* main function to present the output for characters and integers
*
* @param args
*/
public static void main(String[] args) {

// test 1 with integer input
System.out.println("Test:");
EdmondsKarpMaxFlow edmondsKarpTest = new EdmondsKarpMaxFlow(7, 9);
edmondsKarpTest.addEdge(0, 3, 3);
edmondsKarpTest.addEdge(0, 1, 3);
edmondsKarpTest.addEdge(1, 2, 4);
edmondsKarpTest.addEdge(2, 0, 3);
edmondsKarpTest.addEdge(2, 3, 1);
edmondsKarpTest.addEdge(2, 4, 2);
edmondsKarpTest.addEdge(3, 4, 2);
edmondsKarpTest.addEdge(4, 1, 1);
edmondsKarpTest.addEdge(4, 6, 1);
System.out.println("The maximum flow from flowSource to flowTarget is " + (edmondsKarpTest.getMaxFlow(1, 4)) + ".");
}
}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy