Skip to content

Commit 4b5f2b5

Browse files
Updated the code and rewrite some functions
Updated the code and rewrite some functions
1 parent b5daf9f commit 4b5f2b5

File tree

2 files changed

+96
-96
lines changed

2 files changed

+96
-96
lines changed

graph/edmondkarp.ts

-96
This file was deleted.

graph/edmonds_karp.ts

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* @function edmondsKarp
3+
* @description Compute the maximum flow from a source node to a sink node using the Edmonds-Karp algorithm.
4+
* @Complexity_Analysis
5+
* Time complexity: O(V * E^2) where V is the number of vertices and E is the number of edges.
6+
* Space Complexity: O(E) due to residual graph representation.
7+
* @param {[number, number][][]} graph - The graph in adjacency list form.
8+
* @param {number} source - The source node.
9+
* @param {number} sink - The sink node.
10+
* @return {number} - The maximum flow from the source node to the sink node.
11+
* @see https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm
12+
*/
13+
14+
export default function edmondsKarp(
15+
graph: [number, number][][],
16+
source: number,
17+
sink: number
18+
): number {
19+
const n = graph.length
20+
21+
// Initialize residual graph
22+
const residualGraph: [number, number][][] = Array.from(
23+
{ length: n },
24+
() => []
25+
)
26+
27+
// Build residual graph from the original graph
28+
for (let u = 0; u < n; u++) {
29+
for (const [v, cap] of graph[u]) {
30+
if (cap > 0) {
31+
residualGraph[u].push([v, cap]) // Forward edge
32+
residualGraph[v].push([u, 0]) // Reverse edge with 0 capacity
33+
}
34+
}
35+
}
36+
37+
const findAugmentingPath = (parent: (number | null)[]): number => {
38+
const visited = Array(n).fill(false)
39+
const queue: number[] = []
40+
queue.push(source)
41+
visited[source] = true
42+
parent[source] = null
43+
44+
while (queue.length > 0) {
45+
const u = queue.shift()!
46+
for (const [v, cap] of residualGraph[u]) {
47+
if (!visited[v] && cap > 0) {
48+
parent[v] = u
49+
visited[v] = true
50+
if (v === sink) {
51+
// Return the bottleneck capacity along the path
52+
let pathFlow = Infinity
53+
let current = v
54+
while (parent[current] !== null) {
55+
const prev = parent[current]!
56+
const edgeCap = residualGraph[prev].find(
57+
([node]) => node === current
58+
)![1]
59+
pathFlow = Math.min(pathFlow, edgeCap)
60+
current = prev
61+
}
62+
return pathFlow
63+
}
64+
queue.push(v)
65+
}
66+
}
67+
}
68+
return 0
69+
}
70+
71+
let maxFlow = 0
72+
const parent = Array(n).fill(null)
73+
74+
while (true) {
75+
const pathFlow = findAugmentingPath(parent)
76+
if (pathFlow === 0) break // No augmenting path found
77+
78+
// Update the capacities and reverse capacities in the residual graph
79+
let v = sink
80+
while (parent[v] !== null) {
81+
const u = parent[v]!
82+
// Update capacity of the forward edge
83+
const forwardEdge = residualGraph[u].find(([node]) => node === v)!
84+
forwardEdge[1] -= pathFlow
85+
// Update capacity of the reverse edge
86+
const reverseEdge = residualGraph[v].find(([node]) => node === u)!
87+
reverseEdge[1] += pathFlow
88+
89+
v = u
90+
}
91+
92+
maxFlow += pathFlow
93+
}
94+
95+
return maxFlow
96+
}

0 commit comments

Comments
 (0)