Cod sursa(job #3308269)

Utilizator alt_contStefan alt_cont Data 23 august 2025 22:30:12
Problema Flux maxim Scor 70
Compilator rs Status done
Runda Arhiva educationala Marime 3.99 kb
use core::net;
use std::{cmp::{max, min}, collections::{HashMap, VecDeque}, fs::{self, File, OpenOptions}, io::{BufRead, BufReader, BufWriter, Read, Write}};
type Graph = Vec<Vec<(usize, usize)>>;
type Flow = Vec<Vec<(usize, usize, usize)>>; //3 numbers, one keeps the initial capacity information
type ResidualGraph = Vec<Vec<(usize, usize, bool)>>; //keep a boolean to know if the direction is reversed

const INF: usize = 1_000_000_000;

fn main() {
    // read
    let mut file = File::open("maxflow.in").unwrap();
    let mut rdr = BufReader::new(file);
    let mut line = String::new();
    rdr.read_line(&mut line);
    let mut it = line.split_whitespace().map(|x| x.parse::<usize>().unwrap());
    let n = it.next().unwrap();
    let m = it.next().unwrap();
    let mut adj: Graph = vec![vec![]; n + 1];
    for _ in 0..m {
        let mut line = String::new();
        rdr.read_line(&mut line);
        let mut it = line.split_whitespace().map(|x| x.parse::<usize>().unwrap());
        let u = it.next().unwrap();
        let v = it.next().unwrap();
        let c = it.next().unwrap();
        adj[u].push((v, c));
    }
    // dbg!(&adj);

    let mut flow: Flow = vec![vec![]; n + 1];
    // let mut map: Vec<Vec<(usize, usize)>> = vec![vec![(0, 0); n + 1]; n + 1];
    for u in 1..=n {
        for &(v, c) in adj[u].iter() {
            let edge = (v, 0, c);
            flow[u].push(edge);
            // map[u][v] = (0, c);
        }
    }

    loop {
        // dbg!(&flow);
        // construct res graph
        let mut residual: ResidualGraph = vec![vec![]; n + 1];
        for u in 1..=n {
            for &(v, f, c) in flow[u].iter() {
                if c > f {
                    residual[u].push((v, c - f, true));
                }
                if f > 0 {
                    residual[v].push((u, f, false));
                }
            }
        }
        // dbg!(&residual);

        // find augmenting path in the residual
        let mut d = VecDeque::new();
        let mut dist = vec![INF; n + 1];
        let mut paths = vec![(0, 0, false); n + 1]; // parent vector of the augmenting path
        d.push_back(1);
        dist[1] = 0;
        while !d.is_empty() {
            let u = d.pop_front().unwrap();
            for &edge in residual[u].iter() {
                let (v, w, dir) = edge;
                if dist[u] + 1 < dist[v] {
                    dist[v] = dist[u] + 1;
                    d.push_back(v);
                    paths[v] = (u, w, dir);
                }
            }
        }
        // dbg!(&paths);

        // update flow
        if dist[n] == INF {
            break;
        } else {
            let mut v = n;
            let mut edge = &paths[n];
            let mut flux_update = INF;
            while edge.0 != 0 {
                flux_update = min(edge.1, flux_update);
                edge = &paths[edge.0];
            }
            let mut edge = &paths[n];
            // dbg!(edge);
            let mut u; let mut w; let mut dir;
            (u, w, dir) = (edge.0, edge.1, edge.2);

            while u != 0 {
                if dir {
                    // the updates are inefficient, I probably need a different structure to access the flows in O(1)
                    flow[u].iter_mut()
                        .filter(|(end, _, _)| *end == v)
                        .for_each(|(end, f, c)| *f += flux_update);

                    // dbg!(&flow);
                } else {
                    flow[v].iter_mut()
                        .filter(|(end, _, _)| *end == u)
                        .for_each(|(end, f, c)| *f -= flux_update);

                    // dbg!(&flow);
                }
                edge = &paths[u];
                v = u;
                (u, w, dir) = (edge.0, edge.1, edge.2);
            }
        }
    }

    let max_flow: usize = flow[1].iter().map(|&(_, f, _)| f).sum();

    // write
    let ofile= OpenOptions::new().create(true).write(true).truncate(true).open("maxflow.out").unwrap();
    let mut out = BufWriter::new(ofile);
    writeln!(out, "{}", max_flow);
}