Skip to content

Commit cefb14f

Browse files
committed
Improvements in Dinics algo
1 parent c9dbef5 commit cefb14f

1 file changed

Lines changed: 36 additions & 26 deletions

File tree

graph_algorithms/dinic_max_flow.r

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@
1515
# - Airline scheduling
1616
# - Project selection and resource allocation
1717

18+
# Formatting constant
19+
LINE_WIDTH <- 60
20+
1821
#' Create an empty flow network
1922
#' @param n: Number of vertices
2023
#' @return: Flow network structure with adjacency list and capacity matrix
2124
create_flow_network <- function(n) {
22-
list(
23-
n = n,
24-
graph = vector("list", n), # Adjacency list
25-
capacity = matrix(0, nrow = n, ncol = n), # Capacity matrix
26-
flow = matrix(0, nrow = n, ncol = n) # Flow matrix
27-
)
25+
# Use environment to allow in-place (by-reference) mutation without superassignment
26+
env <- new.env(parent = emptyenv())
27+
env$n <- n
28+
env$graph <- vector("list", n) # Adjacency list
29+
env$capacity <- matrix(0, nrow = n, ncol = n) # Capacity matrix
30+
env$flow <- matrix(0, nrow = n, ncol = n) # Flow matrix
31+
return(env)
2832
}
2933

3034
#' Add edge to flow network
@@ -55,24 +59,30 @@ bfs_level_graph <- function(network, source, sink) {
5559
n <- network$n
5660
level <- rep(-1, n)
5761
level[source] <- 0
58-
59-
queue <- c(source)
60-
61-
while (length(queue) > 0) {
62-
u <- queue[1]
63-
queue <- queue[-1]
64-
62+
63+
# O(1) queue using head/tail indices; BFS enqueues each vertex at most once
64+
queue <- integer(n)
65+
head <- 1
66+
tail <- 1
67+
queue[tail] <- source
68+
tail <- tail + 1
69+
70+
while (head < tail) {
71+
u <- queue[head]
72+
head <- head + 1
73+
6574
for (v in network$graph[[u]]) {
6675
# Check if edge has residual capacity and v is not visited
6776
residual_capacity <- network$capacity[u, v] - network$flow[u, v]
68-
77+
6978
if (level[v] == -1 && residual_capacity > 0) {
7079
level[v] <- level[u] + 1
71-
queue <- c(queue, v)
80+
queue[tail] <- v
81+
tail <- tail + 1
7282
}
7383
}
7484
}
75-
85+
7686
return(level)
7787
}
7888

@@ -108,9 +118,9 @@ dfs_send_flow <- function(network, u, sink, level, flow, start) {
108118
)
109119

110120
if (pushed_flow > 0) {
111-
# Update flow
112-
network$flow[u, v] <<- network$flow[u, v] + pushed_flow
113-
network$flow[v, u] <<- network$flow[v, u] - pushed_flow
121+
# Update flow (environment enables in-place mutation)
122+
network$flow[u, v] <- network$flow[u, v] + pushed_flow
123+
network$flow[v, u] <- network$flow[v, u] - pushed_flow
114124
return(pushed_flow)
115125
}
116126
}
@@ -194,21 +204,21 @@ dinic_max_flow <- function(network, source, sink) {
194204
#' @param network: Original network (optional, for displaying edges)
195205
print_max_flow <- function(result, network = NULL) {
196206
cat("Maximum Flow Result:\n")
197-
cat(strrep("=", 60), "\n\n")
207+
cat(strrep("=", LINE_WIDTH), "\n\n")
198208
cat(sprintf("Maximum Flow: %g\n", result$max_flow))
199209
cat(sprintf("Iterations: %d\n\n", result$iterations))
200210

201211
cat("Minimum Cut Edges:\n")
202-
cat(strrep("-", 60), "\n")
212+
cat(strrep("-", LINE_WIDTH), "\n")
203213
if (length(result$min_cut_edges) > 0) {
204214
cat(sprintf("%-15s %-15s %-15s\n", "From", "To", "Capacity"))
205-
cat(strrep("-", 60), "\n")
215+
cat(strrep("-", LINE_WIDTH), "\n")
206216
total_cut_capacity <- 0
207217
for (edge in result$min_cut_edges) {
208218
cat(sprintf("%-15d %-15d %-15g\n", edge$from, edge$to, edge$capacity))
209219
total_cut_capacity <- total_cut_capacity + edge$capacity
210220
}
211-
cat(strrep("-", 60), "\n")
221+
cat(strrep("-", LINE_WIDTH), "\n")
212222
cat(sprintf("Total Cut Capacity: %g\n", total_cut_capacity))
213223
} else {
214224
cat("No cut edges found\n")
@@ -223,9 +233,9 @@ print_max_flow <- function(result, network = NULL) {
223233
#' @param network: Flow network with computed flows
224234
print_flow_edges <- function(network) {
225235
cat("Flow on Edges:\n")
226-
cat(strrep("-", 60), "\n")
236+
cat(strrep("-", LINE_WIDTH), "\n")
227237
cat(sprintf("%-10s %-10s %-12s %-12s\n", "From", "To", "Flow", "Capacity"))
228-
cat(strrep("-", 60), "\n")
238+
cat(strrep("-", LINE_WIDTH), "\n")
229239

230240
for (u in 1:network$n) {
231241
for (v in network$graph[[u]]) {
@@ -235,7 +245,7 @@ print_flow_edges <- function(network) {
235245
}
236246
}
237247
}
238-
cat(strrep("-", 60), "\n\n")
248+
cat(strrep("-", LINE_WIDTH), "\n\n")
239249
}
240250

241251
# ========== Example 1: Basic 6-Vertex Network ==========

0 commit comments

Comments
 (0)