use crate::max_flow::MaxFlow; use itertools::Itertools; use proconio::{input, marker::Usize1}; fn main() { input! { n: usize, m: usize, d: u64, airplains: [(Usize1, Usize1, u64, u64, u64); m], } let mut counter = 0..; let nodes = vec_from_fn(2 * m, |_| counter.next().unwrap()); let source = counter.next().unwrap(); let sink = counter.next().unwrap(); let mut events = vec![vec![]; n]; let mut inst = MaxFlow::new(); for (i, &(u, v, p, q, w)) in airplains.iter().enumerate() { events[u].push((2 * p + 1, nodes[2 * i])); events[v].push((2 * (q + d), nodes[2 * i + 1])); inst.add_edge(2 * i, 2 * i + 1, w); } for e in &mut events { e.sort_unstable(); for ((_, x), (_, y)) in e.iter().copied().tuple_windows() { inst.add_edge(nodes[x], nodes[y], u64::MAX); } } if let Some(&(_, x)) = events[0].first() { inst.add_edge(source, x, u64::MAX); } if let Some(&(_, x)) = events[n - 1].last() { inst.add_edge(x, sink, u64::MAX); } let (flow, _cut) = inst.solve(counter.next().unwrap(), source, sink); println!("{flow}"); } fn vec_from_fn(len: usize, f: impl FnMut(usize) -> T) -> Vec { (0..len).map(f).collect() } // max_flow {{{ // https://ngtkana.github.io/ac-adapter-rs/max_flow/index.html #[allow(unused_imports)] #[allow(dead_code)] mod max_flow { use std::collections::{BinaryHeap, VecDeque}; #[derive(Default, Debug)] pub struct MaxFlow { pub edges: Vec, } impl MaxFlow { pub fn new() -> Self { Self::default() } pub fn add_edge(&mut self, src: usize, tar: usize, cap: u64) { self.edges.push(Edge { src, tar, cap, flow: 0, }); self.edges.push(Edge { src: tar, tar: src, cap, flow: cap, }); } pub fn original_edges(&self) -> Vec { self.edges.iter().step_by(2).copied().collect() } pub fn solve(&mut self, n: usize, source: usize, sink: usize) -> (u64, Vec) { let Self { edges } = self; let mut g = vec![vec![]; n]; for (i, &e) in edges.iter().enumerate() { g[e.src].push(i); } let mut excess = vec![0; n]; for &i in &g[source] { let y = edges[i].tar; let f = edges[i].cap - edges[i].flow; if y == source || f == 0 { continue; } excess[y] += f; edges[i].flow += f; edges[i ^ 1].flow -= f; } let mut height = vec![n + 1; n]; let mut queue = VecDeque::new(); height[source] = n; height[sink] = 0; queue.push_back(sink); while let Some(x) = queue.pop_front() { for &i in &g[x] { let y = edges[i].tar; if y != sink && height[y] == n + 1 && edges[i].flow != 0 { height[y] = height[x] + 1; queue.push_back(y); } } } let mut heap = (0..n) .filter(|&x| x != source && x != sink && excess[x] != 0) .map(|x| (height[x], x)) .collect::>(); 'pop: while let Some((_, x)) = heap.pop() { for &i in &g[x] { let y = edges[i].tar; if edges[i].flow == edges[i].cap || height[x] <= height[y] { continue; } let f = excess[x].min(edges[i].cap - edges[i].flow); if excess[y] == 0 && y != source && y != sink { heap.push((height[y], y)); } edges[i].flow += f; edges[i ^ 1].flow -= f; excess[x] -= f; excess[y] += f; if excess[x] == 0 { continue 'pop; } } assert!(excess[x] > 0); height[x] = g[x] .iter() .filter(|&&i| edges[i].flow < edges[i].cap) .map(|&i| height[edges[i].tar]) .min() .unwrap() + 1; heap.push((height[x], x)); } let cut = height.iter().map(|&h| h >= n).collect(); let flow = excess[sink]; (flow, cut) } } #[derive(Debug, Default, Clone, Copy, PartialEq)] pub struct Edge { pub src: usize, pub tar: usize, pub cap: u64, pub flow: u64, } } // }}}