fn main() { let mut io = IO::new(); let (n, m): (usize, usize) = io.scan(); let mut ns: NetworkSimplex = NetworkSimplex::new(); for _ in 0..m { let (u, v, c, d): (usize, usize, i64, i64) = io.scan(); let u = u - 1; let v = v - 1; ns.add_edge(u, v, 0, 1, c); ns.add_edge(v, u, 0, 1, c); ns.add_edge(u, v, 0, 1, d); ns.add_edge(v, u, 0, 1, d); } ns.add_supply(0, 2); ns.add_demand(n-1, 2); let ret = ns.run().unwrap(); let ans = ret.get_value::(); io.println(ans); } // ------------ traits start ------------ use std::fmt::Display; pub trait Cost: Element + Display + Copy + Eq + Ord + Zero + One + Add + AddAssign + Sub + Neg { fn is_positive(&self) -> bool { self > &Self::zero() } fn is_negative(&self) -> bool { self < &Self::zero() } } pub trait Flow: Cost + SubAssign { fn abs(&self) -> Self { if self.is_negative() { -*self } else { *self } } } macro_rules! impl_flow { ($($T:ty,)*) => { $( impl Flow for $T {} impl Cost for $T {} )* }; } impl_flow!( i8, i16, i32, i64, i128, isize, ); // ------------ traits end ------------ use std::cmp::{ max, min }; use std::collections::HashSet; struct Edge { src: usize, dst: usize, flow: F, capacity: F, cost: C, } #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)] pub struct EdgeId(usize); impl EdgeId { fn rev(self) -> Self { EdgeId(self.0 ^ 1) } } struct VertexData { potential: C, adjacent_edges: Vec, parent: Option, parent_edge: Option, // out-tree, i.e. this node == e.src depth: usize, tree_edges: HashSet, } impl Default for VertexData { fn default() -> Self { Self { potential: C::zero(), adjacent_edges: Vec::new(), parent: None, parent_edge: None, depth: 0, tree_edges: HashSet::new(), } } } #[derive(Default)] pub struct NetworkSimplex { edges: Vec>, balances: Vec, } struct TemporaryData { vertices: Vec>, n: usize, root: usize, block_size: usize, next_scan_start: usize, } pub struct Ret { edges: Vec<(F, C)>, potential: Vec, } impl Ret { pub fn get_value(&self) -> T where T: From + From + Mul + Add + Zero, { self.edges .iter() .filter(|(f, _)| f.is_positive()) .map(|(f, c)| T::from(*f) * T::from(*c)) .fold(T::zero(), |a, b| a + b) } pub fn get_flow(&self, e: EdgeId) -> F { self.edges[e.0].0 } pub fn get_potential(&self, v: usize) -> C { self.potential[v] } } impl NetworkSimplex { pub fn new() -> Self { Self { edges: Vec::new(), balances: Vec::new(), } } pub fn add_edge(&mut self, src: usize, dst: usize, lower: F, upper: F, cost: C) -> EdgeId { assert!( lower <= upper, "lower {} should be less or equal to upper {}", lower, upper ); let id = self.edges.len(); self.edges.push(Edge { src, dst, flow: lower, capacity: upper, cost, }); self.edges.push(Edge { src: dst, dst: src, flow: -lower, capacity: -lower, cost: -cost, }); if !lower.is_zero() { self.add_demand(src, lower); self.add_supply(dst, lower); } EdgeId(id) } pub fn add_supply(&mut self, v: usize, b: F) { let n = max(v + 1, self.balances.len()); self.balances.resize_with(n, F::zero); self.balances[v] += b; } pub fn add_demand(&mut self, v: usize, b: F) { self.add_supply(v, -b); } fn get_edge(&self, e: EdgeId) -> &Edge { &self.edges[e.0] } fn get_edge_mut(&mut self, e: EdgeId) -> &mut Edge { &mut self.edges[e.0] } /// return true iff this was a saturating push fn add_flow(&mut self, e: EdgeId, f: F) -> bool { self.get_edge_mut(e.rev()).flow -= f; let e = self.get_edge_mut(e); e.flow += f; e.flow == e.capacity } fn residual_capacity(e: &Edge) -> F { e.capacity - e.flow } fn reduced_cost(data: &TemporaryData, e: &Edge) -> C { e.cost + data.vertices[e.src].potential - data.vertices[e.dst].potential } fn update_tree(&self, data: &mut TemporaryData, v: usize) { let mut stack = vec![v]; while let Some(v) = stack.pop() { let adj = std::mem::take(&mut data.vertices[v].tree_edges); for &eid in adj.iter() { let e = self.get_edge(eid); if data.vertices[v].parent == Some(e.dst) { continue; } data.vertices[e.dst].parent = Some(v); data.vertices[e.dst].parent_edge = Some(eid.rev()); data.vertices[e.dst].depth = data.vertices[e.src].depth + 1; data.vertices[e.dst].potential = data.vertices[e.src].potential + e.cost; stack.push(e.dst); } data.vertices[v].tree_edges = adj; } } fn prepare_data(&mut self) -> TemporaryData { // allocate root vertex let mut infinity = C::one(); let mut data = TemporaryData { vertices: Default::default(), n: self.balances.len(), root: 0, block_size: 1, next_scan_start: 0, }; data.vertices.clear(); for (i, e) in self.edges.iter().enumerate() { data.n = max(data.n, 1 + e.src); data.vertices.resize_with(data.n, Default::default); data.vertices[e.src].adjacent_edges.push(EdgeId(i)); if e.cost.is_positive() { infinity += e.cost; } } data.root = data.n; data.n += 1; let root = data.root; data.vertices.resize_with(data.n, Default::default); self.balances.resize_with(data.n - 1, F::zero); for v in 0..root { let b = std::mem::replace(&mut self.balances[v], F::zero()); let (x, y, cap) = if b.is_negative() { (root, v, -b) } else { (v, root, b + F::one()) }; let eid = self.add_edge(x, y, F::zero(), cap, infinity); self.add_flow(eid, b.abs()); data.vertices[x].adjacent_edges.push(eid); data.vertices[y].adjacent_edges.push(eid.rev()); data.vertices[x].tree_edges.insert(eid); data.vertices[y].tree_edges.insert(eid.rev()); } data.block_size = min( (self.edges.len() as f64).sqrt() as usize + 10, self.edges.len(), ); self.update_tree(&mut data, root); data } fn select_edge(&mut self, data: &mut TemporaryData) -> Option { let mut edges = (data.next_scan_start..self.edges.len()) .chain(0..data.next_scan_start) .map(EdgeId) .peekable(); while edges.peek().is_some() { let mut selection = Option::None; for _ in 0..data.block_size { match edges.next() { None => { break; } Some(id) => { let e = self.get_edge_mut(id); if e.flow == e.capacity { continue; } let rc = Self::reduced_cost(data, e); if rc.is_negative() { let candidate = (rc, id); if let Some(current) = selection.take() { selection = Some(min(current, candidate)) } else { selection = Some(candidate) } } } } } if let Some((_, eid)) = selection { if let Some(nid) = edges.peek() { data.next_scan_start = nid.0; } return Some(eid); } } None } fn pivot(&mut self, data: &mut TemporaryData, eid: EdgeId) { let entering_edge = self.get_edge(eid); let Edge { src, dst, .. } = *entering_edge; let mut f = Self::residual_capacity(entering_edge); let mut a = src; let mut b = dst; while a != b { if data.vertices[a].depth > data.vertices[b].depth { let down_edge = data.vertices[a].parent_edge.unwrap().rev(); let e = self.get_edge(down_edge); f = min(f, Self::residual_capacity(e)); a = e.src; } else { let up_edge = data.vertices[b].parent_edge.unwrap(); let e = self.get_edge(up_edge); f = min(f, Self::residual_capacity(e)); b = e.dst; } } enum LeavingSide { SRC, DST, ENTER, } let mut leaving_side = LeavingSide::ENTER; let top = a; let mut leaving_edge_id = None; a = src; while a != top { let v_data = &data.vertices[a]; let down_edge = v_data.parent_edge.unwrap().rev(); if self.add_flow(down_edge, f) && leaving_edge_id.is_none() { leaving_edge_id = Some(down_edge); leaving_side = LeavingSide::SRC; } a = v_data.parent.unwrap(); } if self.add_flow(eid, f) { leaving_edge_id = Some(eid); leaving_side = LeavingSide::ENTER; } b = dst; while b != top { let v_data = &data.vertices[b]; let up_edge = v_data.parent_edge.unwrap(); if self.add_flow(up_edge, f) { leaving_edge_id = Some(up_edge); leaving_side = LeavingSide::DST; } b = v_data.parent.unwrap(); } let leaving_edge_id = leaving_edge_id.unwrap(); let leaving_e = self.get_edge(leaving_edge_id); if leaving_edge_id == eid { return; } assert!(data.vertices[src].tree_edges.insert(eid)); assert!(data.vertices[dst].tree_edges.insert(eid.rev())); assert!(data.vertices[leaving_e.src] .tree_edges .remove(&leaving_edge_id)); assert!(data.vertices[leaving_e.dst] .tree_edges .remove(&leaving_edge_id.rev())); match leaving_side { LeavingSide::SRC => self.update_tree(data, dst), LeavingSide::DST => self.update_tree(data, src), LeavingSide::ENTER => (), } } pub fn run(&mut self) -> Option> { let mut data = self.prepare_data(); while let Some(eid) = self.select_edge(&mut data) { self.pivot(&mut data, eid); } for e in self.edges.split_off(self.edges.len() - 2 * (data.n - 1)) { if !e.flow.is_zero() { return None; } } Some(Ret { edges: self.edges.iter().map(|e| (e.flow, e.cost)).collect(), potential: data .vertices .iter() .take(data.n - 1) .map(|v| v.potential) .collect(), }) } } // ------------ libraries start ------------ // ------------ libraries end ------------ // ------------ traits start ------------ use std::marker::Sized; use std::ops::*; /// 元 pub trait Element: Sized + Clone + PartialEq {} impl Element for T {} /// 結合性 pub trait Associative: Magma {} /// マグマ pub trait Magma: Element + Add {} impl> Magma for T {} /// 半群 pub trait SemiGroup: Magma + Associative {} impl SemiGroup for T {} /// モノイド pub trait Monoid: SemiGroup + Zero {} impl Monoid for T {} pub trait ComMonoid: Monoid + AddAssign {} impl ComMonoid for T {} /// 群 pub trait Group: Monoid + Neg {} impl> Group for T {} pub trait ComGroup: Group + ComMonoid {} impl ComGroup for T {} /// 半環 pub trait SemiRing: ComMonoid + Mul + One {} impl + One> SemiRing for T {} /// 環 pub trait Ring: ComGroup + SemiRing {} impl Ring for T {} pub trait ComRing: Ring + MulAssign {} impl ComRing for T {} /// 体 pub trait Field: ComRing + Div + DivAssign {} impl + DivAssign> Field for T {} /// 加法単元 pub trait Zero: Element { fn zero() -> Self; fn is_zero(&self) -> bool; } /// 乗法単元 pub trait One: Element { fn one() -> Self; fn is_one(&self) -> bool; } macro_rules! impl_integer { ($($T:ty,)*) => { $( impl Associative for $T {} impl Zero for $T { fn zero() -> Self { 0 } fn is_zero(&self) -> bool { *self == 0 } } impl<'a> Zero for &'a $T { fn zero() -> Self { &0 } fn is_zero(&self) -> bool { *self == &0 } } impl One for $T { fn one() -> Self { 1 } fn is_one(&self) -> bool { *self == 1 } } impl<'a> One for &'a $T { fn one() -> Self { &1 } fn is_one(&self) -> bool { *self == &1 } } )* }; } impl_integer! { i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, } // ------------ traits end ------------ // ------------ io module start ------------ use std::io::{stdout, BufWriter, Read, StdoutLock, Write}; pub struct IO { iter: std::str::SplitAsciiWhitespace<'static>, buf: BufWriter>, } impl IO { pub fn new() -> Self { let mut input = String::new(); std::io::stdin().read_to_string(&mut input).unwrap(); let input = Box::leak(input.into_boxed_str()); let out = Box::new(stdout()); IO { iter: input.split_ascii_whitespace(), buf: BufWriter::new(Box::leak(out).lock()), } } fn scan_str(&mut self) -> &'static str { self.iter.next().unwrap() } fn scan_raw(&mut self) -> &'static [u8] { self.scan_str().as_bytes() } pub fn scan(&mut self) -> T { T::scan(self) } pub fn scan_vec(&mut self, n: usize) -> Vec { (0..n).map(|_| self.scan()).collect() } } impl IO { pub fn print(&mut self, x: T) { T::print(self, x); } pub fn println(&mut self, x: T) { self.print(x); self.print("\n"); } pub fn iterln>(&mut self, mut iter: I, delim: &str) { if let Some(v) = iter.next() { self.print(v); for v in iter { self.print(delim); self.print(v); } } self.print("\n"); } pub fn flush(&mut self) { self.buf.flush().unwrap(); } } impl Default for IO { fn default() -> Self { Self::new() } } pub trait Scan { fn scan(io: &mut IO) -> Self; } macro_rules! impl_parse_int { ($($t:tt),*) => { $( impl Scan for $t { fn scan(s: &mut IO) -> Self { let mut res = 0; let mut neg = false; for d in s.scan_raw() { if *d == b'-' { neg = true; } else { res *= 10; res += (*d - b'0') as $t; } } if neg { res = res.wrapping_neg(); } res } } )* }; } impl_parse_int!(i16, i32, i64, isize, u16, u32, u64, usize); impl Scan for (T, U) { fn scan(s: &mut IO) -> Self { (T::scan(s), U::scan(s)) } } impl Scan for (T, U, V) { fn scan(s: &mut IO) -> Self { (T::scan(s), U::scan(s), V::scan(s)) } } impl Scan for (T, U, V, W) { fn scan(s: &mut IO) -> Self { (T::scan(s), U::scan(s), V::scan(s), W::scan(s)) } } pub trait Print { fn print(w: &mut IO, x: Self); } macro_rules! impl_print_int { ($($t:ty),*) => { $( impl Print for $t { fn print(w: &mut IO, x: Self) { w.buf.write_all(x.to_string().as_bytes()).unwrap(); } } )* }; } impl_print_int!(i16, i32, i64, isize, u16, u32, u64, usize); impl Print for u8 { fn print(w: &mut IO, x: Self) { w.buf.write_all(&[x]).unwrap(); } } impl Print for &[u8] { fn print(w: &mut IO, x: Self) { w.buf.write_all(x).unwrap(); } } impl Print for &str { fn print(w: &mut IO, x: Self) { w.print(x.as_bytes()); } } impl Print for (T, U) { fn print(w: &mut IO, (x, y): Self) { w.print(x); w.print(" "); w.print(y); } } impl Print for (T, U, V) { fn print(w: &mut IO, (x, y, z): Self) { w.print(x); w.print(" "); w.print(y); w.print(" "); w.print(z); } } impl Print for (T, U, V, W) { fn print(w: &mut IO, (x, y, z, a): Self) { w.print(x); w.print(" "); w.print(y); w.print(" "); w.print(z); w.print(" "); w.print(a); } } // ------------ io module end ------------