diff --git a/src/flow/flow.rs b/src/flow/flow.rs
new file mode 100644
index 0000000..d49e522
--- /dev/null
+++ b/src/flow/flow.rs
@@ -0,0 +1,84 @@
+use crate::flow::adjacencies::Adjacencies;
+use crate::flow::Node;
+use crate::types::{Address, Edge, U256};
+use std::cmp::min;
+use std::collections::HashMap;
+use std::collections::VecDeque;
+
+pub fn compute_flow(source: &Address, sink: &Address, edges: &HashMap
>) {
+ let mut adjacencies = Adjacencies::new(edges);
+ let mut used_edges: HashMap> = HashMap::new();
+
+ let mut flow = U256::default();
+ loop {
+ let (new_flow, parents) = augmenting_path(source, sink, &mut adjacencies);
+ if new_flow == U256::default() {
+ break;
+ }
+ flow += new_flow;
+ for window in parents.windows(2) {
+ if let [node, prev] = window {
+ adjacencies.adjust_capacity(prev, node, -new_flow);
+ adjacencies.adjust_capacity(node, prev, new_flow);
+ if adjacencies.is_adjacent(node, prev) {
+ *used_edges
+ .entry(node.clone())
+ .or_default()
+ .entry(prev.clone())
+ .or_default() -= new_flow;
+ } else {
+ *used_edges
+ .entry(prev.clone())
+ .or_default()
+ .entry(node.clone())
+ .or_default() -= new_flow;
+ }
+ } else {
+ panic!();
+ }
+ }
+ }
+ println!("Max flow: {flow}");
+}
+
+fn augmenting_path(
+ source: &Address,
+ sink: &Address,
+ adjacencies: &mut Adjacencies,
+) -> (U256, Vec) {
+ let mut parent = HashMap::new();
+ if *source == *sink {
+ return (U256::default(), vec![]);
+ }
+ let mut queue = VecDeque::<(Node, U256)>::new();
+ queue.push_back((Node::Node(*source), U256::default() - U256::from(1)));
+ while let Some((node, flow)) = queue.pop_front() {
+ for (target, capacity) in adjacencies.outgoing_edges_sorted_by_capacity(&node) {
+ if !parent.contains_key(&target) && capacity > U256::default() {
+ parent.insert(target.clone(), node.clone());
+ let new_flow = min(flow, capacity);
+ if target == Node::Node(*sink) {
+ return (
+ new_flow,
+ trace(parent, &Node::Node(*source), &Node::Node(*sink)),
+ );
+ }
+ queue.push_back((target, new_flow));
+ }
+ }
+ }
+ (U256::default(), vec![])
+}
+
+fn trace(parent: HashMap, source: &Node, sink: &Node) -> Vec {
+ let mut t = vec![sink.clone()];
+ let mut node = sink;
+ loop {
+ node = parent.get(node).unwrap();
+ t.push(node.clone());
+ if *node == *source {
+ break;
+ }
+ }
+ t
+}