diff --git a/assignment-3/push-relabel.odin b/assignment-3/push-relabel.odin index d16df21..d13aac0 100644 --- a/assignment-3/push-relabel.odin +++ b/assignment-3/push-relabel.odin @@ -2,7 +2,6 @@ package main import "core:fmt" import "core:math" -import "core:slice" // the graph starts with a source s and ends with a sink t, hence the 1s. // then there is a stack of n nodes, then a chain of k nodes, then another stack of m nodes. @@ -61,7 +60,7 @@ print_graph :: proc(g: [$row][$col]$T, elem_sep := " ", line_sep := "\n") { fmt.print(rune('a' + i)) // row markers fmt.print(elem_sep) for j in 0 ..< col { - fmt.print(g[i][j]) + fmt.print(g[i][j] < 0 ? 10 + g[i][j] : g[i][j]) fmt.print(elem_sep) } fmt.print(line_sep) @@ -74,7 +73,7 @@ find_node_with_excess :: proc(excesses: []int) -> (u: int, ok: bool) { } find_admissible_edge :: proc(u: int, residuals, heights: []int) -> (v: int, ok: bool) { - if len(residuals) != len(heights) do return -1, false + assert(len(residuals) == len(heights)) for r, idx in residuals { if r > 0 && heights[u] == heights[idx] + 1 { return idx, true @@ -83,14 +82,16 @@ find_admissible_edge :: proc(u: int, residuals, heights: []int) -> (v: int, ok: return -1, false } -push :: proc(u, v: int, residuals, excesses: []int) -> (res: []int, ok: bool) { - if len(residuals) != excesses +push :: proc(u, v: int, residuals, excesses: []int) -> int { + assert(len(residuals) == len(excesses)) + return min(excesses[u], residuals[v]) } push_relabel :: proc(graph: [$n][n]int) -> (flow: [n][n]int) { heights: [n]int heights[0] = n flow[0] += graph[0] + for _, idx in flow do flow[idx][0] -= graph[idx][0] excesses: [n]int excesses[0] = -math.sum(flow[0][:]) excesses += flow[0] @@ -99,9 +100,20 @@ push_relabel :: proc(graph: [$n][n]int) -> (flow: [n][n]int) { u += 1 residuals := graph[u] - flow[u] if v, ok := find_admissible_edge(u, residuals[:], heights[:]); ok { - flow[u] = push(u, v, residuals[:], excesses[:]) + assert(heights[u] == heights[v] + 1) + delta := push(u, v, residuals[:], excesses[:]) + flow[u][v] += delta + flow[v][u] -= delta + excesses[u] -= delta + excesses[v] += delta } else { - // relabel(u, v, graph, flow) + assert(excesses[u] > 0) + for r, v in residuals do if r > 0 do assert(heights[u] <= heights[v]) + m := n + for h, v in heights { + if residuals[v] > 0 do m = h < m ? h : m + } + heights[u] = 1 + m } } return @@ -110,7 +122,8 @@ push_relabel :: proc(graph: [$n][n]int) -> (flow: [n][n]int) { main :: proc() { graph := create_graph(3, 3, 3, 3) - print_graph(graph, elem_sep = " ") + print_graph(graph, elem_sep = " ") fmt.println() - print_graph(push_relabel(graph)) + print_graph(push_relabel(graph), elem_sep = " ") } +