Cod sursa(job #3138664)

Utilizator TincaMateiTinca Matei TincaMatei Data 21 iunie 2023 03:49:02
Problema Ciclu Eulerian Scor 60
Compilator rs Status done
Runda Arhiva educationala Marime 12.69 kb
#![allow(dead_code)]

use std::io::{Read, BufRead, Stdin, BufReader};
use std::fs::File;
use std::str::FromStr;
use std::fmt::Debug;

pub struct InParser<T: Read> {
    reader: BufReader<T>,
    buffer: Vec<u8>,
    cursor: usize,
    eof_flag: bool,
}

impl InParser<Stdin> {
    pub fn from_stdin() -> InParser<Stdin> {
        InParser::new(std::io::stdin())
    }
}

impl InParser<File> {
    pub fn from_filename(name: &str) -> InParser<File> {
        InParser::new(File::open(name)
                      .expect("Failed to open file"))
    }
}

impl<T: Read> InParser<T> {
    pub fn new(reader: T) -> InParser<T> {
        let mut reader = BufReader::new(reader);

        let buffer = reader.fill_buf()
            .expect("Failed to fill buffer")
            .to_vec();
        
        InParser {
            reader,
            buffer,
            cursor: 0,
            eof_flag: false,
        }
    }
    
    pub fn get_current_byte(&mut self) -> u8 {
        if self.cursor < self.buffer.len() {
            return self.buffer[self.cursor]; 
        }
        panic!("Outside of buffer")
    }

    pub fn advance_cursor(&mut self) {
        self.cursor += 1;
        if self.cursor >= self.buffer.len() {
            self.reader.consume(self.buffer.len());
            self.buffer = self.reader.fill_buf()
                .expect("Failed to fill buffer")
                .to_vec();

            self.eof_flag = self.buffer.is_empty();
            self.cursor = 0;
        }
    }

    fn skip_spaces(&mut self) {
        while !self.eof_flag && 
            (self.get_current_byte() == b' ' ||
             self.get_current_byte() == b'\n') {
            
            self.advance_cursor();
        }
    }

    fn get_token(&mut self) -> Vec<u8> {
        let mut token_buf: Vec<u8> = Vec::new();

        self.skip_spaces();

        while !self.eof_flag &&
            self.get_current_byte() != b' ' &&
            self.get_current_byte() != b'\n' {
            
            let byte = self.get_current_byte();
            token_buf.push(byte);

            self.advance_cursor();
        }

        token_buf
    }
   
    pub fn read_string(&mut self) -> String {
        let token = self.get_token();
        
        let strval = std::str::from_utf8(&token)
            .expect("Failed to convert into valid utf8")
            .trim();

        strval.to_string()
    }
    
    pub fn read_number<F: From<i64>>(&mut self) -> F {
        self.skip_spaces();

        let sgn = if self.get_current_byte() == b'-' {
            self.advance_cursor();
            -1
        } else {
            1
        };
        let mut nr = 0;

        while !self.eof_flag && self.get_current_byte().is_ascii_digit() {
            nr = nr * 10 + (self.get_current_byte() - b'0') as i64;
            self.advance_cursor();
        }

        F::from(nr * sgn)
    }

    pub fn read<F>(&mut self) -> F
    where F: FromStr,
          <F as FromStr>::Err: Debug {
        self.read_string().parse::<F>()
            .unwrap()
    }
}

use std::io::{Write, BufWriter, Stdout};

pub struct OutParser<T: Write> {
    writer: BufWriter<T>,
}

impl<T: Write> OutParser<T> {
    pub fn new(writer: T) -> OutParser<T> {
        OutParser {
            writer: BufWriter::new(writer)
        }
    }

    pub fn write<F: ToString>(&mut self, val: F) -> &mut Self {
        self.writer.write(&val.to_string().as_bytes())
            .expect("Failed to write");
        
        self
    }
}

impl OutParser<Stdout> {
    pub fn from_stdout() -> OutParser<Stdout> {
        OutParser::new(std::io::stdout())
    }
}

impl OutParser<File> {
    pub fn from_filename(name: &str) -> OutParser<File> {
        OutParser::new(File::create(name)
                       .expect("Failed to open file"))
    }
}

pub trait Edge {
    /// Returns the index of the edge.
    fn edge_index(&self) -> usize;
    
    /// Returns the nodes that the edge connects. The edge goes from the first to the second node.
    fn as_pair(&self) -> (usize, usize);

    /// Returns the opposite node from the given endpoint.
    ///
    /// This is useful when having undirected graphs, as each edge is stored only once.
    fn other(&self, from: usize) -> usize;
}

/// Indexed directed edge.
///
/// If the graph is undirected, then there will be two directed edges
/// with the same index.
#[derive(Debug, Copy, Clone)]
pub struct DirectedEdge {
    pub id: usize,
    pub from: usize,
    pub to: usize,
}

impl DirectedEdge {
    /// Create a new edge.
    pub fn new(from: usize, to: usize, id: usize) -> DirectedEdge{
        DirectedEdge { from, to, id }
    }
}

impl Edge for DirectedEdge {
    fn edge_index(&self) -> usize { self.id }
    fn as_pair(&self) -> (usize, usize) { (self.from, self.to) }
    fn other(&self, from: usize) -> usize { self.from ^ self.to ^ from }
}

/// General purpose graph structure.
///
/// `V` specifies the type of data stored in each node. `E` is the type of the edges used.
#[derive(Debug)]
pub struct Graph<V, E> 
where V: Default,
      E: Edge {
    
    /// The information stored in each node.
    pub nodes: Vec<V>,

    /// The set of all edges.
    pub edges: Vec<E>,

    /// The adjacency list of the graph. Each element in the list is the index of the edge.
    pub adj: Vec<Vec<usize>>
}

impl<V, E> Graph<V, E> 
where V: Default + Copy,
      E: Edge + Copy {
    
    /// Returns the number of nodes in the graph.
    pub fn v(&self) -> usize { self.nodes.len() }

    /// Returns the number of edges in the graph.
    pub fn e(&self) -> usize { self.edges.len() }

    /// Creates a new graph with `v` nodes that has no edges.
    pub fn empty(v: usize) -> Graph<V, E> {
        Graph {
            nodes: vec![V::default(); v],
            edges: vec![],
            adj: vec![Vec::new(); v],
        }
    }
    
    /// Creates a new **directed** graph with `v` nodes and the given edge set.
    pub fn from_edges(v: usize, edges: &Vec<E>) -> Graph<V, E> {
        let mut g = Graph::<V, E>::empty(v);
        
        for edge in edges {
            g.push_edge(*edge);
        }

        g
    }
    
    /// Creates an **undirected** graph with `v` nodes and the given edge set.
    pub fn from_undirected_edges(v: usize, edges: &Vec<E>) -> Graph<V, E> {
        let mut g = Graph::<V, E>::empty(v);
        
        for edge in edges {
            g.push_undirected_edge(*edge);
        }

        g
    }

    /// Pushes a **directed** edge in the graph.
    pub fn push_edge(&mut self, e: E) {
        let (a, _) = e.as_pair();
        let id = self.edges.len();
        self.edges.push(e);
        self.adj[a].push(id);
    }

    /// Pushes an **undirected** edge in the graph.
    pub fn push_undirected_edge(&mut self, e: E) {
        let (a, b) = e.as_pair();
        let id = self.edges.len();
        self.edges.push(e);
        self.adj[a].push(id);
        self.adj[b].push(id);
    }
}

/// This is the most basic graph that you would need for general purpose graphs.
pub type BasicGraph = Graph<(), DirectedEdge>;

impl BasicGraph {
    /// Create a **directed** [BasicGraph] from the number of nodes and the edges as pairs.
    ///
    /// The edges go from the first node to the second node in the pair.
    pub fn from_pairs(v: usize, e: &Vec<(usize, usize)>) -> BasicGraph {
        let mut g = BasicGraph::empty(v);

        for edge in e {
            let (a, b) = *edge;
            let id = g.edges.len();
            g.push_edge(DirectedEdge::new(id, a, b) );
        }

        g
    }
    
    /// Create an **undirected** [BasicGraph] from the number of nodes and the edges as pairs.
    pub fn from_undirected_pairs(v: usize, e: &Vec<(usize, usize)>) -> BasicGraph {
        let mut g = BasicGraph::empty(v);

        for edge in e {
            let (a, b) = *edge;
            let id = g.edges.len();
            g.push_undirected_edge(DirectedEdge { id, from: a, to: b} );
        }

        g
    }
}

use std::slice::Iter;

fn eulerian_cycle_dfs(graph: &BasicGraph, 
                          res: &mut Vec<usize>,
                          iterators: &mut Vec<Iter<'_, usize>>,
                          visited_edge: &mut Vec<bool>,
                          node: usize) {
    
    let mut current_edge = iterators[node].next();

    while current_edge != None {
        let id = *current_edge.unwrap();
        let it = graph.edges[id].other(node);

        if !visited_edge[id] {
            visited_edge[id] = true;

            eulerian_cycle_dfs(graph, res, iterators, visited_edge, it);
        }

        
        current_edge = iterators[node].next();
    }
    
    res.push(node);
}

fn get_euler_start(graph: &BasicGraph) -> Option<usize> {
    let mut degree = vec![0i32; graph.nodes.len()];

    for edge in &graph.edges {
        let (a, b) = (edge.from, edge.to);

        degree[a] += 1;
        degree[b] -= 1;
    }

    let mut positive = 0;
    let mut negative = 0;
    let mut start = 0;

    for (node, degree) in degree.iter().enumerate() {
        if degree > &0 {
            positive += 1;
            start = node;
        } else if degree < &0 {
            negative += 1;
        }

        if positive > 1 || negative > 1 {
            return None;
        }
    }

    Some(start)
}

/// Checks if the **directed** graph has an eulerian path. If it does, it returns it.
///
/// The array returned is the indexes of each node, in the order of the traversal.
pub fn eulerian_path(graph: &BasicGraph) -> Option<Vec<usize>> {
    let start = get_euler_start(graph);

    match start {
    Some(start) => {
        let mut res = Vec::new();
        
        let mut iterators = Vec::new();
        for i in 0..graph.nodes.len() {
            iterators.push(graph.adj[i].iter());
        }

        let mut visited_edges = vec![false; graph.e()];

        eulerian_cycle_dfs(graph, 
                           &mut res, 
                           &mut iterators, 
                           &mut visited_edges,
                           start);
        if !visited_edges.iter().all(|v| *v) {
            return None;
        }

        res.reverse();
        Some(res)
    }
    None => None
    }
}

fn get_euler_undirected_start(graph: &BasicGraph) -> Option<usize> {
    let mut degree = vec![0i32; graph.nodes.len()];

    for edge in &graph.edges {
        let (a, b) = (edge.from, edge.to);

        degree[a] += 1;
        degree[b] += 1;
    }

    let mut odds_count = 0;
    let mut start = 0;

    for (node, degree) in degree.iter().enumerate() {
        if degree % 2 == 1 {
            odds_count += 1;
            start = node;
        }

        if odds_count > 2 {
            return None;
        }
    }

    Some(start)
}

/// Checks if the **undirected** graph has an eulerian path. If it does, it returns it.
///
/// The array returned is the indexes of each node, in the order of the traversal.
pub fn eulerian_undirected_path(graph: &BasicGraph) -> Option<Vec<usize>> {
    let start = get_euler_undirected_start(graph);

    match start {
    Some(start) => {
        let mut res = Vec::new();
        
        let mut iterators = Vec::new();
        for i in 0..graph.nodes.len() {
            iterators.push(graph.adj[i].iter());
        }
        let mut visited_edges = vec![false; graph.e()];

        eulerian_cycle_dfs(graph, 
                           &mut res, 
                           &mut iterators, 
                           &mut visited_edges,
                           start);

        if !visited_edges.iter().all(|p| *p) {
            return None;
        }

        Some(res)
    }
    None => None
    }
}

// Solve the task with the given input and print it to the given output.
fn solve_test<I: Read, O: Write>(fin: &mut InParser<I>, fout: &mut OutParser<O>) {
    let (n, m): (usize, usize) = (fin.read(), fin.read());
    let edges: Vec<(usize, usize)> = (0..m)
        .map(|_| (fin.read::<usize>() - 1, fin.read::<usize>() - 1) )
        .collect();

    let graph = BasicGraph::from_undirected_pairs(n, &edges);
    
    let res = eulerian_undirected_path(&graph);

    match res {
    None => {
        fout.write(-1);
    },
    Some(path) => {
        for node in &path {
            fout.write(node + 1);
            fout.write(' ');
        }
    }
    }
} 

// Run a sample with the given input and check with the correct output.
fn try_sample(input: &[u8], ok: &str) {
    use std::io::Cursor;

    let mut output = Vec::<u8>::new();

    solve_test(&mut InParser::new(BufReader::new(Cursor::new(input))),
               &mut OutParser::new(BufWriter::new(&mut output)));

    assert_eq!(std::str::from_utf8(&output).unwrap(), ok);
}

// Run the first sample of the problem.
// dang it, I can't test these >:(
fn sample_1() {
    try_sample(br#"1 2"#, r#"3"#);
}

fn main() {
    //sample_1();
    
    solve_test(&mut InParser::from_filename("ciclueuler.in"),
               &mut OutParser::from_filename("ciclueuler.out"));
}