Max Flow
Overview
The Max Flow algorithm computes the maximum amount of flow that can be routed through a directed, weighted graph from one or more source nodes to one or more sink (target) nodes. Edge weights represent capacities — the upper bound on how much flow an edge can carry.
Max Flow is commonly applied in scenarios such as:
- Network throughput optimization (bandwidth, pipelines, logistics)
- Traffic routing and congestion analysis
- Supply chain and distribution planning
- Bipartite matching and scheduling problems
Algorithm Details
The procedure implements a capacity-scaling max-flow algorithm over the subgraph induced by the specified node labels and relationship types. It builds a residual graph from the selected edges (using the configured capacity property), then repeatedly finds augmenting paths from the source super-node to the sink super-node and pushes flow along them until no augmenting path exists.
Multiple source or sink nodes are supported by introducing a virtual super-source connected to every source node, and a virtual super-sink connected from every sink node, each with infinite capacity.
The algorithm returns the set of nodes and edges that carry positive flow, together with the per-edge flow values and the total maximum flow.
Performance
The algorithm operates with a time complexity of O(V · E²), where:
-
** V ** represents the total number of nodes in the subgraph -
** E ** represents the total number of edges in the subgraph
For sparse graphs this is typically much faster in practice.
Syntax
CALL algo.maxFlow(config)
YIELD nodes, edges, edgeFlows, maxFlow
Parameters
The procedure accepts a required configuration Map with the following parameters:
| Name | Type | Default | Description |
|---|---|---|---|
sourceNodes |
Array | (required) | One or more node objects that act as flow sources |
targetNodes |
Array | (required) | One or more node objects that act as flow sinks |
relationshipTypes |
Array | (required) | Relationship types that define the edges of the flow network |
capacityProperty |
String | 'capacity' |
Name of the numeric edge property used as the edge capacity |
nodeLabels |
Array | All labels | Array of node labels used to restrict which nodes are included |
Return Values
The procedure yields a single record with the following fields:
| Name | Type | Description |
|---|---|---|
nodes |
Array | All node entities that participate in the max-flow solution (carry positive flow) |
edges |
Array | All edge entities that carry positive flow |
edgeFlows |
Array | Numeric flow value for each edge in edges, in the same order |
maxFlow |
Integer | The total maximum flow from all source nodes to all sink nodes |
Examples
Consider this pipeline network:
(A) --[cap:10]--> (B) --[cap:8]--> (C)
\ ^
\----------[cap:5]---------------/
Node A is the source, node C is the sink. There are two routes from A to C:
- A → C directly, with capacity 5
- A → B → C, with a bottleneck of 8 (min of 10 and 8)
The maximum flow is therefore 13.
Create the Graph
CREATE
(a:Node {name: 'A'}),
(b:Node {name: 'B'}),
(c:Node {name: 'C'}),
(a)-[:PIPE {cap: 10}]->(b),
(a)-[:PIPE {cap: 5}]->(c),
(b)-[:PIPE {cap: 8}]->(c)
Example: Compute the maximum flow between two nodes
MATCH (s:Node {name: 'A'}), (t:Node {name: 'C'})
CALL algo.maxFlow({
sourceNodes: [s],
targetNodes: [t],
capacityProperty: 'cap',
relationshipTypes: ['PIPE']
})
YIELD nodes, edges, edgeFlows, maxFlow
RETURN maxFlow
Expected Results
| maxFlow |
|---|
13 |
Example: Inspect per-edge flow on the solution
MATCH (s:Node {name: 'A'}), (t:Node {name: 'C'})
CALL algo.maxFlow({
sourceNodes: [s],
targetNodes: [t],
capacityProperty: 'cap',
relationshipTypes: ['PIPE']
})
YIELD edges, edgeFlows
UNWIND range(0, size(edges) - 1) AS i
RETURN
startNode(edges[i]).name AS from,
endNode(edges[i]).name AS to,
edgeFlows[i] AS flow
Expected Results
| from | to | flow |
|---|---|---|
A |
B |
8 |
A |
C |
5 |
B |
C |
8 |
Example: Restrict the subgraph by node label
When the graph contains multiple node labels, use nodeLabels to limit the algorithm to a specific subset of nodes:
MATCH (s:Intersection {name: 'Source'}), (t:Intersection {name: 'Sink'})
CALL algo.maxFlow({
sourceNodes: [s],
targetNodes: [t],
capacityProperty: 'bandwidth',
nodeLabels: ['Intersection'],
relationshipTypes: ['CONNECTS']
})
YIELD nodes, maxFlow
RETURN size(nodes) AS participatingNodes, maxFlow
Example: Multiple sources and multiple sinks
sourceNodes and targetNodes each accept arrays, allowing multi-commodity-style problems to be modelled with virtual super-nodes:
MATCH
(s1:Node {name: 'SourceA'}),
(s2:Node {name: 'SourceB'}),
(t:Node {name: 'Sink'})
CALL algo.maxFlow({
sourceNodes: [s1, s2],
targetNodes: [t],
capacityProperty: 'cap',
relationshipTypes: ['PIPE']
})
YIELD maxFlow
RETURN maxFlow