@@ -161,6 +161,106 @@ class Graph<T> {
161161 return false ;
162162 } ;
163163
164+ // For Ford-Fulkerson
165+ // Returns boolean for an existing augmenting path, and the path between s -> t
166+ augmentingPath = ( s : T , t : T , g : Graph < T > ) => {
167+ const { dist, parents } = g . bfs ( s ) ;
168+ const exists = dist . get ( t ) !== undefined ? true : false ;
169+ if ( ! exists ) return { exists : false , path : undefined } ;
170+ const path = this . getPath ( s , t , parents ) ;
171+ return { exists, path } ;
172+ } ;
173+
174+ getPath = ( s : T , t : T , parents : Map < T , T | null > ) => {
175+ // go back from t until we reach s
176+ const path : Array < T > = [ ] ;
177+ let a = parents . get ( t ) ! ;
178+ path . push ( t ) ;
179+ while ( a !== s ) {
180+ path . push ( a ) ;
181+ a = parents . get ( a ) ! ;
182+ }
183+ path . push ( s ) ;
184+ return path . reverse ( ) ;
185+ } ;
186+
187+ // Returns the smallest capacity that remains in a path between s - t in a Net-Flow
188+ bottleneck = ( path : Array < T > , g : Graph < T > ) => {
189+ let min = Infinity ;
190+ // for each edge(u,v) of this path check the capacity that remains
191+ for ( let i = 0 ; i < path . length - 1 ; i ++ ) {
192+ const u = path [ i ] ;
193+ const v = path [ i + 1 ] ;
194+ const list = g . list . get ( u ) ! ;
195+ // search for v in adj list of u
196+ for ( let node of list ) {
197+ if ( v === node . node ) {
198+ // check if edge(u,v) < min
199+ if ( min > node . weight ) {
200+ min = node . weight ;
201+ }
202+ }
203+ }
204+ }
205+ return min ;
206+ } ;
207+
208+ createResidualGraph = ( ) => {
209+ const rg = new Graph < T > ( true ) ;
210+ for ( let [ u , vertexList ] of this . list ) {
211+ for ( let v in vertexList ) {
212+ // original edge = c(u,v)
213+ rg . addVertecesAndEdge ( u , vertexList [ v ] . node , vertexList [ v ] . weight ) ;
214+ // residual edges
215+ rg . addVertecesAndEdge ( vertexList [ v ] . node , u , 0 ) ;
216+ }
217+ }
218+ return rg ;
219+ } ;
220+
221+ updateResidualGraph = ( g : Graph < T > , path : Array < T > , bottleneck : number ) => {
222+ // for each edge of this path
223+ for ( let i = 0 ; i < path . length - 1 ; i ++ ) {
224+ // we need to check if edge(u,v) is from the original Graph or from the Residual Graph
225+ // let isResidual = true;
226+ const u = path [ i ] ;
227+ const v = path [ i + 1 ] ;
228+ const listU = g . list . get ( u ) ! ;
229+ const listV = g . list . get ( v ) ! ;
230+ let updatedEdgeUV : Vertex < T > ;
231+ let updatedEdgeVU : Vertex < T > ;
232+ // search for edge(u,v) in residual graph
233+ for ( let i = 0 ; i < listU . length ; i ++ ) {
234+ const t = listU [ i ] ;
235+ if ( v == t . node ) {
236+ updatedEdgeUV = {
237+ node : t . node ,
238+ weight : t . weight - bottleneck ,
239+ } ;
240+ const updatedList = [ ...listU ] ;
241+ updatedList [ i ] = updatedEdgeUV ;
242+ g . list . set ( u , updatedList ) ;
243+ break ;
244+ }
245+ }
246+ // search for edge(v,v) in residual graph
247+ for ( let i = 0 ; i < listV . length ; i ++ ) {
248+ const t = listV [ i ] ;
249+ if ( u == t . node ) {
250+ updatedEdgeVU = {
251+ node : t . node ,
252+ weight : t . weight + bottleneck ,
253+ } ;
254+ const updatedList = [ ...listV ] ;
255+ updatedList [ i ] = updatedEdgeVU ;
256+ g . list . set ( v , updatedList ) ;
257+ break ;
258+ }
259+ }
260+ }
261+ return g ;
262+ } ;
263+
164264 // **********************************************************
165265 // INSERT
166266 // **********************************************************
@@ -456,7 +556,7 @@ class Graph<T> {
456556 // Maps the key of each vertex to its distance from vertex s
457557 const dist : Map < T , number > = new Map ( ) ;
458558 // Maps the key of each vertex to its parents key
459- const parents : Map < T , null | string > = new Map ( ) ;
559+ const parents : Map < T , null | T > = new Map ( ) ;
460560 const visited : Map < T , boolean > = new Map ( ) ;
461561 const q : Queue = new Queue ( ) ;
462562 // add s to the queue
@@ -471,7 +571,7 @@ class Graph<T> {
471571 result . push ( v . key ) ;
472572 this . list . get ( v . key ) ! . forEach ( ( u ) => {
473573 // if u unvisited
474- if ( ! visited . get ( u . node ) ) {
574+ if ( ! visited . get ( u . node ) && u . weight > 0 ) {
475575 // mark u as visited
476576 visited . set ( u . node , true ) ;
477577 // add u to the queue
@@ -949,6 +1049,40 @@ class Graph<T> {
9491049 }
9501050 return { cost, MST } ;
9511051 } ;
1052+
1053+ // Returns the final Residual Graph
1054+ fordFulkerson = ( s : T , t : T ) => {
1055+ if ( ! this . directed ) return false ;
1056+ const flow = new Map < T , Map < T , number > > ( ) ;
1057+ // Initially f(e)=0 for all e in G
1058+ // for each edge of G f(u,v) = 0
1059+ for ( let [ u , vertexList ] of this . list ) {
1060+ flow . set ( u , new Map < T , number > ( ) ) ;
1061+ for ( let v of vertexList ) {
1062+ flow . get ( u ) ! . set ( v . node , 0 ) ;
1063+ }
1064+ }
1065+ let residualGraph : Graph < T > = this . createResidualGraph ( ) ;
1066+ residualGraph . print ( ) ;
1067+ let { exists, path } = this . augmentingPath ( s , t , residualGraph ) ;
1068+ // if there is no path between s - t return false
1069+ if ( ! exists || ! path ) return false ;
1070+
1071+ const bottleneck = this . bottleneck ( path , residualGraph ) ;
1072+ // while exists a path do augmenting path in Gr
1073+ while ( exists ) {
1074+ const bottleneck = this . bottleneck ( path ! , residualGraph ) ;
1075+ residualGraph = this . updateResidualGraph (
1076+ residualGraph ,
1077+ path ! ,
1078+ bottleneck
1079+ ) ;
1080+ const ap = this . augmentingPath ( s , t , residualGraph ) ;
1081+ exists = ap . exists ;
1082+ path = ap . path ;
1083+ }
1084+ return residualGraph ;
1085+ } ;
9521086}
9531087
9541088export = Graph ;
0 commit comments