Cod sursa(job #3141457)

Utilizator TincaMateiTinca Matei TincaMatei Data 14 iulie 2023 01:23:19
Problema Ciclu Eulerian Scor 100
Compilator rs Status done
Runda Arhiva educationala Marime 8.47 kb
pub use __cargo_equip::prelude::*;

use dopecomp_euler::find_eulerian_cycle;
use dopecomp_graph::Graph;
use dopecomp_io::{InParser, OutParser};
use std::io::{Read, Write};

fn solve_test<I: Read, O: Write>(fin: &mut InParser<I>, fout: &mut OutParser<O>) {
    let (n, m) = (fin.read(), fin.read());
    let mut edges: Vec<(usize, usize)> = Vec::with_capacity(m);

    for _ in 0..m {
        // should use read_number
        let (a, b): (usize, usize) = (fin.read::<usize>() - 1, fin.read::<usize>() - 1);
        edges.push((a, b));
    }

    let graph = Graph::<(), (usize, usize)>::from_edges(n, edges, |x| x, true);

    let cycle = find_eulerian_cycle(&graph);

    match cycle {
        None => {
            fout.write("-1");
        }
        Some(result) => {
            for e in result {
                fout.write(e + 1);
                fout.write(" ");
            }
        }
    }
}

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

// The following code was expanded by `cargo-equip`.

///  # Bundled libraries
/// 
///  - `dopecomp_euler 0.1.0 (git+https://github.com/tincaMatei/competitive-rust#7eb8b8cb339c6c64f448b287858932e15a77862d)` licensed under **missing** as `crate::__cargo_equip::crates::dopecomp_euler`
///  - `dopecomp_graph 0.1.0 (git+https://github.com/tincaMatei/competitive-rust#7eb8b8cb339c6c64f448b287858932e15a77862d)` licensed under **missing** as `crate::__cargo_equip::crates::dopecomp_graph`
///  - `dopecomp_io 0.1.0 (git+https://github.com/tincaMatei/competitive-rust#7eb8b8cb339c6c64f448b287858932e15a77862d)`    licensed under **missing** as `crate::__cargo_equip::crates::dopecomp_io`
#[cfg_attr(any(), rustfmt::skip)]
#[allow(unused)]
mod __cargo_equip {
    pub(crate) mod crates {
        pub mod dopecomp_euler {use crate::__cargo_equip::preludes::dopecomp_euler::*;use crate::__cargo_equip::crates::dopecomp_graph as dopecomp_graph;use dopecomp_graph::{Graph,Edge};struct EulerianCycleSolver<'a,V,E>where V:Default,E:Edge{graph:&'a Graph<V,E>,used_edge:Vec<bool>,last_edge:Vec<usize>,result:Vec<usize>,}impl<'a,V,E>EulerianCycleSolver<'a,V,E>where V:Default,E:Edge{fn eulerian_dfs(&mut self,node:usize){while self.last_edge[node]<self.graph.adj_list[node].len(){let cnt_edge=self.last_edge[node];let id=self.graph.adj_list[node][cnt_edge];if!self.used_edge[id]{let other=self.graph.edges[id].to(node);self.used_edge[id]=true;self.eulerian_dfs(other);}self.last_edge[node]+=1;}self.result.push(node);}}pub fn solve_eulerian<V,E>(graph:&Graph<V,E>,undirected:bool,cycle:bool)->Option<Vec<usize>>where V:Default,E:Edge{let mut degree=vec![0;graph.v()];for node in 0..graph.v(){for it in&graph.adj_list[node]{let edge=&graph.edges[*it];degree[edge.to(node)]+=1;}}let mut start_node=0;let mut cnt_even=0;let mut cnt_pos=0;let mut cnt_neg=0;for node in 0..graph.v(){if undirected&&degree[node]%2==1{start_node=node;cnt_even+=1;}else if!undirected&&degree[node]<graph.adj_list[node].len(){start_node=node;cnt_pos+=1;}else if!undirected&&degree[node]>graph.adj_list[node].len(){cnt_neg+=1;}}if undirected{if cnt_even>2{return None;}if cycle&&cnt_even>0{return None;}}else{if cnt_pos>1||cnt_neg>1{return None;}if cycle&&(cnt_pos>0||cnt_neg>0){return None;}}let mut solver=EulerianCycleSolver{graph,used_edge:vec![false;graph.e()],last_edge:vec![0;graph.v()],result:Vec::with_capacity(graph.e()+1),};solver.eulerian_dfs(start_node);if solver.result.len()!=graph.e()+1{None}else{if!undirected{solver.result.reverse();}Some(solver.result)}}pub fn find_eulerian_cycle<V,E>(graph:&Graph<V,E>)->Option<Vec<usize>>where V:Default,E:Edge{solve_eulerian(graph,graph.undirected,true)}pub fn find_eulerian_path<V,E>(graph:&Graph<V,E>)->Option<Vec<usize>>where V:Default,E:Edge{solve_eulerian(graph,graph.undirected,false)}}
        pub mod dopecomp_graph {pub trait Edge{fn to(&self,from:usize)->usize;}pub trait BidirectionalEdge:Edge{fn as_pair(&self)->(usize,usize);}#[derive(Debug)]pub struct Graph<V,E>where V:Default,E:Edge{pub nodes:Vec<V>,pub edges:Vec<E>,pub adj_list:Vec<Vec<usize>>,pub undirected:bool,}impl<V,E>Graph<V,E>where V:Default,E:Edge{pub fn from_edges<T,F>(v:usize,edges:Vec<T>,transf:F,undirected:bool)->Graph<V,E>where T:BidirectionalEdge,F:Fn(T)->E{let mut nodes=Vec::with_capacity(v);for _ in 0..v{nodes.push(V::default());}let mut capacity=vec![0;v];for e in&edges{let(a,b)=e.as_pair();capacity[a]+=1;if undirected{capacity[b]+=1;}}let mut adj_list:Vec<Vec<usize>> =Vec::with_capacity(v);for i in 0..v{adj_list.push(Vec::with_capacity(capacity[i]));}for id in 0..edges.len(){let edge=&edges[id];let(a,b)=edge.as_pair();adj_list[a].push(id);if undirected{adj_list[b].push(id);}}let edges:Vec<E> =edges.into_iter().map(transf).collect();Graph::<V,E>{nodes,edges,adj_list,undirected}}pub fn with_capacity(v:usize,e:usize,undirected:bool)->Graph<V,E>{Graph::<V,E>{nodes:(0..v).map(|_|V::default()).collect(),edges:Vec::with_capacity(e),adj_list:vec![Vec::new();v],undirected}}pub fn push_directed_edge(&mut self,from:usize,edge:E){let id=self.edges.len();self.edges.push(edge);self.adj_list[from].push(id);}pub fn push_undirected_edge(&mut self,edge:E)where E:BidirectionalEdge{let id=self.edges.len();let(a,b)=edge.as_pair();self.edges.push(edge);self.adj_list[a].push(id);self.adj_list[b].push(id);}pub fn v(&self)->usize{self.nodes.len()}pub fn e(&self)->usize{self.edges.len()}}impl Edge for usize{fn to(&self,_:usize)->usize{*self}}impl Edge for(usize,usize){fn to(&self,from:usize)->usize{return self.0^self.1^from;}}impl BidirectionalEdge for(usize,usize){fn as_pair(&self)->(usize,usize){return*self;}}}
        pub mod dopecomp_io {#![allow(dead_code)]use std::io::{Read,BufRead,Stdin,BufReader,Write,BufWriter,Stdout};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()}}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(crate) mod macros {
        pub mod dopecomp_euler {}
        pub mod dopecomp_graph {}
        pub mod dopecomp_io {}
    }

    pub(crate) mod prelude {pub use crate::__cargo_equip::crates::*;}

    mod preludes {
        pub mod dopecomp_euler {pub(in crate::__cargo_equip)use crate::__cargo_equip::crates::dopecomp_graph;}
        pub mod dopecomp_graph {}
        pub mod dopecomp_io {}
    }
}