-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFordFulkerson.java
More file actions
130 lines (104 loc) · 4.99 KB
/
FordFulkerson.java
File metadata and controls
130 lines (104 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import java.util.*;
/* Ford Fulkerson code implementation from:
https://www.sanfoundry.com/java-program-implement-ford-fulkerson-algorithm/
https://www.geeksforgeeks.org/minimum-cut-in-a-directed-graph/*/
public class FordFulkerson {
private int numOfVertices;
private Set<Pair> cutSet;
public FordFulkerson(int numOfVertices) {
this.numOfVertices = numOfVertices;
this.cutSet = new HashSet<Pair>();
}
public int maxFlowMinCut(Graph graph, int src, int dest) {//finding max flow and cutting-edges of the network
int u;
int v;
int maxFlow=0;
int[][] residualGraph=new int[numOfVertices][numOfVertices];
for (int i = 0; i < graph.size(); i++) {
for (int j = 0; j < graph.size(); j++) {
residualGraph[i][j]=graph.getEdge(i,j);//at first, residual graph edge capacity = graph edge capacity
}
}
int[] parent = new int[numOfVertices];//for storing paths
// Augmenting max path flows to assign residual graph edge capacities
while (bfs(residualGraph, src, dest, parent)) {//if there is an existing path src to dest. Check by comparing with parent array in bfs
int pathFlow = Integer.MAX_VALUE;
for (v = dest; v != src; v = parent[v]) {
u = parent[v];
pathFlow = Math.min(pathFlow, residualGraph[u][v]);//maximum flow through the path,min capacity
}
// updating residual capacity of the edge and reverse edge in the residual graph based on possible max flow through that path
for (v = dest; v != src; v = parent[v]) {//through one possible path through src->dest finding min capacity
u = parent[v];
residualGraph[u][v] -= pathFlow;//subtract from forward edge and that is the package left
residualGraph[v][u] += pathFlow;//add to reverse edge since package can send
}
maxFlow+=pathFlow;//adding each max flow through paths to total max flow of network
}
// finding vertices reachable from src
boolean[] visited = new boolean[numOfVertices];
for(int i=0; i< visited.length; i++){
visited[i]=false;
}
dfs(residualGraph, src, visited);//mark reachable vertices from source as visited
// Cutting-edges are vertex pairs from reachable vertex to non-reachable vertex in the original graph
for (int i = 0; i < numOfVertices; i++) {
for (int j = 0; j < numOfVertices; j++) {
if (graph.getEdge(i,j) > 0 && visited[i] && !visited[j]) {
if(i!=src && j!= dest) {
Pair pair = new Pair(i, j, graph.getEdge(i, j));
cutSet.add(pair);//cutSet=cutting-edge pairs
}
}
}
}
return maxFlow;
}
public static boolean bfs(int[][] residualGraph, int src, int dest, int[] parent) {
boolean[] visited = new boolean[residualGraph.length];// to avoid cycles marking visited edge as true
Queue<Integer> queue = new LinkedList<Integer>();
queue.add(src);// enqueue source vertex and mark source vertex as visited
visited[src] = true;
parent[src] = -1;
//bfs
while (!queue.isEmpty()) {
int u = queue.poll();//returns the element at the front
for (int v = 0; v < residualGraph.length; v++) {
if (residualGraph[u][v] > 0 && !visited[v]) {
queue.add(v);
visited[v] = true;
parent[v] = u;
}
}
}
//If source -> dest is reachable than there is path return true,else return false
return (visited[dest] == true);
}
public static void dfs(int[][] residualGraph, int src, boolean[] visited) {
visited[src] = true;
for (int i = 0; i < residualGraph.length; i++) {
if (residualGraph[src][i] > 0 && !visited[i]) {//if there is path and not visited
dfs(residualGraph, i, visited);
}
}
}
public Iterator<Pair> getCutSet () {//get cut set to use in main for optimization
return cutSet.iterator();
}
public void printCutSet(ArrayList<Pair>cutting_edges_List,ArrayList<String>vertices){
for (int i = 0; i < cutting_edges_List.size(); i++) {
Pair pair = cutting_edges_List.get(i);
System.out.println(vertices.get(pair.source )+ "-" + vertices.get(pair.destination));
}
}
}
class Pair{//Nested Class to keep cutting edge pairs
public int source;
public int destination;
public int initialCapacity;
public Pair (int source, int destination, int initialCapacity) {
this.source = source;
this.destination = destination;
this.initialCapacity=initialCapacity;
}
}