networking_flow.push_relabel¶
Push-relabel (Goldberg-Tarjan) algorithm for the maximum-flow problem.
The push-relabel method takes a very different approach from the augmenting-path
algorithms in this directory (ford_fulkerson.py builds up a valid flow one
path at a time). Instead it works with a preflow, in which a vertex may
temporarily receive more flow than it sends out. Each active vertex either
pushes its excess towards a neighbour that is one level lower, or is relabeled
to a higher level so that a push becomes possible. When no vertex other than the
source and sink has excess, the preflow has become a maximum flow.
Using the highest-label selection rule (always discharge an active vertex whose label is largest) this implementation runs in O(V^2 * sqrt(E)) time, which beats the augmenting-path methods on dense graphs.
Reference: https://en.wikipedia.org/wiki/Push%E2%80%93relabel_maximum_flow_algorithm
Classes¶
Maximum flow in a directed graph with non-negative integer capacities. |
Module Contents¶
- class networking_flow.push_relabel.PushRelabel(vertices: int)¶
Maximum flow in a directed graph with non-negative integer capacities.
Add edges with
add_edge(), then callmax_flow().>>> g = PushRelabel(6) >>> capacities = { ... (0, 1): 16, (0, 2): 13, (1, 2): 10, (1, 3): 12, ... (2, 1): 4, (2, 4): 14, (3, 2): 9, (3, 5): 20, ... (4, 3): 7, (4, 5): 4, ... } >>> for (u, v), cap in capacities.items(): ... g.add_edge(u, v, cap) >>> g.max_flow(0, 5) 23
It agrees with the classic four-vertex example:
>>> h = PushRelabel(4) >>> for (u, v), cap in {(0, 1): 3, (0, 2): 2, (1, 2): 5, ... (1, 3): 2, (2, 3): 3}.items(): ... h.add_edge(u, v, cap) >>> h.max_flow(0, 3) 5
Parallel edges add up, and a disconnected sink gives zero flow:
>>> p = PushRelabel(2) >>> p.add_edge(0, 1, 3) >>> p.add_edge(0, 1, 5) >>> p.max_flow(0, 1) 8 >>> PushRelabel(3).max_flow(0, 2) 0
- _apply_pushes(u: int, height: list[int], excess: list[int]) None¶
Push as much excess as possible from
ualong admissible edges.
- _discharge(u: int, height: list[int]) bool¶
Return
Trueifuhas at least one admissible outgoing edge.
- add_edge(source: int, destination: int, capacity: int) None¶
Add a directed edge
source -> destinationwith the given capacity.>>> g = PushRelabel(2) >>> g.add_edge(0, 1, -1) Traceback (most recent call last): ... ValueError: capacity must be non-negative >>> g.add_edge(2, 0, 1) Traceback (most recent call last): ... ValueError: vertex out of range
- max_flow(source: int, sink: int) int¶
Return the maximum flow from
sourcetosink.>>> PushRelabel(2).max_flow(0, 0) Traceback (most recent call last): ... ValueError: source and sink must be different
- size¶