#![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"));
}