#![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 {
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>>,
}
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
}
}
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;
}
}
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 {
pub 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 eulerian_path<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)
}
}
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 = eulerian_path(
&graph,
true,
true
);
match cycle {
None => {
fout.write("-1");
}
Some(result) => {
for e in result {
fout.write(e + 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"));
}