题目描述
求有向图字典序最小的欧拉路径。
输入格式
第一行两个整数 n,m 表示有向图的点数和边数。
接下来 m 行每行两个整数 u,v 表示存在一条 u→v 的有向边。
输出格式
如果不存在欧拉路径,输出一行 No
。
否则输出一行 m+1 个数字,表示字典序最小的欧拉路径。
样例
输入
4 6
1 3
2 1
4 2
3 3
1 2
3 4
输出
1 2 1 3 3 4 2
输入
5 5
1 2
3 5
4 3
3 4
2 3
输出
1 2 3 4 3 5
输入
4 3
1 2
1 3
1 4
输出
No
说明/提示
对于 50% 的数据,n,m≤103 。
对于 100% 的数据,1≤u,v≤n≤105,m≤2×105。
保证将有向边视为无向边后图连通。
分析
这里以样例一为例进行分析。样例一的有向图如下所示:
首先找到欧拉路径的起点,即出度比入度大一的点。容易发现顶点1的出度为2,入度为1,因此,顶点1是欧拉路径的起点。
具体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| use std::collections::VecDeque;
fn main() { let mut graph = read_graph(); let mut result = Vec::new(); if let Ok((start, _end)) = check(&graph) { dfs(&mut graph, start, &mut result); result.push(start); result.reverse(); for x in result { print!("{} ", x+1); } } else { println!("No"); }
}
fn check(graph: &Vec<VecDeque<usize>>) -> Result<(usize, usize), ()> {
let mut in_degree = vec![0; graph.len()]; let mut out_degree = vec![0; graph.len()];
for u in 0..graph.len() { for v in graph[u].iter() { out_degree[u] += 1; in_degree[*v] += 1; } }
let magic_number = 0x80000000usize; let mut start = magic_number; let mut end = magic_number;
for i in 0..graph.len() { if out_degree[i] == in_degree[i] { continue; } else if out_degree[i] > in_degree[i] && out_degree[i] - in_degree[i] == 1 { if start != magic_number { return Err(()); } else { start = i; } } else if in_degree[i] > out_degree[i] && in_degree[i] - out_degree[i] == 1 { if end != magic_number { return Err(()); } else { end = i; } } else { return Err(()); } }
if start == magic_number { start = 0; end = 0; }
let mut queue = VecDeque::new(); let mut visit = vec![false; graph.len()];
queue.push_back(start); visit[start] = true; while ! queue.is_empty() { let u = queue.pop_front().unwrap(); assert!( visit[u] );
for v in graph[u].iter() { if visit[*v] { continue; } visit[*v] = true; queue.push_back(*v); } }
for flag in visit.iter() { if ! *flag { return Err(()); } }
Ok((start, end)) }
fn dfs(graph: &mut Vec<VecDeque<usize>>, current_vec: usize, result: &mut Vec<usize>) {
while ! graph[current_vec].is_empty() { let front = graph[current_vec].pop_front().unwrap(); dfs(graph, front, result); result.push(front); } }
fn read_graph() -> Vec<VecDeque<usize>> { let mut buf = String::new(); std::io::stdin().read_line(&mut buf).unwrap(); let mut numbers = buf.trim().split(" "); let n = numbers.next().unwrap().parse::<usize>().unwrap(); let m = numbers.next().unwrap().parse::<usize>().unwrap();
let mut graph: Vec<VecDeque<usize>> = vec![VecDeque::new(); n];
for _ in 0..m { buf.clear(); std::io::stdin().read_line(&mut buf).unwrap(); let mut numbers = buf.trim().split(" "); let u = numbers.next().unwrap().parse::<usize>().unwrap() - 1; let v = numbers.next().unwrap().parse::<usize>().unwrap() - 1;
assert!(u < n); assert!(v < n); graph[u].push_back(v); }
for raw in graph.iter_mut() { raw.make_contiguous().sort(); }
graph
}
|