Cod sursa(job #3308173)

Utilizator alt_contStefan alt_cont Data 23 august 2025 14:07:57
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator rs Status done
Runda Arhiva educationala Marime 3.38 kb
use std::{cmp::max, collections::VecDeque, fs::{self, File, OpenOptions}, io::{BufRead, BufReader, BufWriter, Read, Write}};

fn read_graph(rdr: &mut BufReader<File>, l: usize, k: usize) -> Vec<Vec<usize>> {
    let mut adj: Vec<Vec<usize>> = vec![vec![]; l + 1];
    for _ in 0..k {
        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();
        adj[u].push(v);
    }
    adj
}

fn main() {
    // read
    let mut file = File::open("cuplaj.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 l = it.next().unwrap();
    let r = it.next().unwrap();
    let k = it.next().unwrap();
    let mut adj: Vec<Vec<usize>> = vec![vec![]; l + 1];
    for _ in 0..k {
        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();
        adj[u].push(v);
    }

    let mut matchL: Vec<i32> = vec![-1; l + 1];
    let mut matchR: Vec<i32> = vec![-1; r + 1];
    let mut dist = vec![-1; l + 1];

    let mut matching = 0;
    while bfs(&adj, &matchL, &matchR, &mut dist, l) {
        for u in 1..=l {
            if matchL[u] == -1 && dfs(u, &adj, &mut matchL, &mut matchR, &mut dist) {
                matching += 1;
            }
        }
    }
    // dbg!(&matchL, &matchR, matching);

    // write
    let ofile= OpenOptions::new().create(true).write(true).truncate(true).open("cuplaj.out").unwrap();
    let mut out = BufWriter::new(ofile);
    writeln!(out, "{} ", matching);
    for u in 1..=l {
        if matchL[u] != -1 {
            writeln!(out, "{} {}", u, matchL[u]);
        }
    }
}

fn bfs(adj: &Vec<Vec<usize>>, matchL: &Vec<i32>, matchR: &Vec<i32>, dist: &mut Vec<i32>, l: usize) -> bool {
    // dbg!("BFS: ", &matchL, &matchR, &dist);
    let mut d: VecDeque<usize> = VecDeque::new();
    for u in 1..=l {
        if matchL[u] == -1 {
            d.push_back(u);
            dist[u] = 0;
        } else {
            dist[u] = -1;
        } 
    }
    let mut found_path = false;
    // dbg!("BFS 2: ", &dist, &d);
    let mut path_len = 1_000_000_000;
    while !d.is_empty() {
        let u = d.pop_front().unwrap();
        for v in adj[u].iter() {
            let w = matchR[*v];
            // dbg!(u, v, w);
            // dbg!(&dist, &d);
            if w == -1 {
                found_path = true;
                path_len = dist[u];
            } else if (dist[w as usize] == -1 && dist[u] < path_len) {
                d.push_back(w as usize);
                dist[w as usize] = dist[u] + 1;
            }
        }
    }
    // dbg!("BFS 3: ", &dist, &d);
    return found_path;
}

fn dfs (u: usize, adj: &Vec<Vec<usize>>, matchL: &mut Vec<i32>, matchR: &mut Vec<i32>, dist: &mut Vec<i32>) -> bool {
    // dbg!("DFS: ", u, &matchL, &matchR, &dist);
    for &v in &adj[u] {
        let w = matchR[v];
        if w == -1 || (dist[w as usize] == dist[u] + 1 && dfs(w as usize, adj, matchL, matchR, dist)) {
            matchR[v] = u as i32;
            matchL[u] = v as i32;
            return true;
        } 
    }
    dist[u] = -1;
    return false;
}