Flow.
This commit is contained in:
parent
d886e03aa4
commit
df7877ea37
1 changed files with 84 additions and 0 deletions
84
src/flow/flow.rs
Normal file
84
src/flow/flow.rs
Normal file
|
@ -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<Address, Vec<Edge>>) {
|
||||||
|
let mut adjacencies = Adjacencies::new(edges);
|
||||||
|
let mut used_edges: HashMap<Node, HashMap<Node, U256>> = 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<Node>) {
|
||||||
|
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<Node, Node>, source: &Node, sink: &Node) -> Vec<Node> {
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in a new issue