题目来源:哥尼斯堡七桥问题的无向多重图推广。
学习目标
前置知识与环境
先阅读DFS 与 BFS 基础。需要 C++17 编译器,运行前可执行 make doctor。
题目
给定每座桥的两端,输出一次走完所有桥且不重复的路线,或判定不可行。允许同一对地点之间有多座桥以及自环。为使课程判题唯一,使用如下 Hierholzer 规则:有两个奇度顶点时从较小者出发;否则从最小非零度顶点出发;无边时起点为 0。每次从当前点选择 (邻点编号, 输入边编号) 最小的尚未使用边入栈;没有可用边时弹出顶点并追加到逆序答案,最后整体反转。
输入格式
第一行 n m,后 m 行 u v。顶点 0..n-1,边编号 1..m。1 ≤ n ≤ 10000,0 ≤ m ≤ 100000。允许自环、重边、非连通图。
输出格式
不可行输出 Not Eulerian。可行时第一行输出 m,第二行输出按上述规则得到的 m+1 个顶点。无边时输出两行 0 和 0。该规则指定构造顺序,不额外宣称任意贪心行走都能得到合法路线。
样例输入
3 3
0 1
1 2
2 0样例输出
3
0 1 2 0样例解释
从最小非零度顶点 0 开始,规范化 Hierholzer 得到 0→1→2→0,三条边各用一次。
任务
- 检查奇度条件并确定规范起点。
- 按排序后的邻接表执行栈式 Hierholzer。
- 检查逆序答案长度为 m+1,反转并输出。
在 student/main.cpp 的 TODO 处完成算法。起始代码可以编译,但不代表已经实现题目;参考实现位于 solution/main.cpp。
正常、边界与错误情况
必须按边编号标记使用状态;只标记顶点或把平行桥合并会漏边。
输入保证符合上述格式与范围,不要求处理损坏输入。无解、不可达等情况按本题输出合同处理,不视为格式错误。测试点包含如下场景,每点 5 分,共 100 分:
| 测试点 | 类型 |
|---|---|
001-sample | 样例 |
002-singleton-empty | 边界 |
003-many-isolated | 边界 |
004-isolated-zero | 易错反例 |
005-two-disconnected-cycles | 易错反例 |
006-two-odd | 易错反例 |
007-four-odd | 易错反例 |
008-seven-bridges | 易错反例 |
009-self-loop | 易错反例 |
010-parallel-bridges | 易错反例 |
011-bridge-must-be-spliced | 易错反例 |
012-disconnected-loops | 易错反例 |
013-seeded-walk-0 | 正常 |
014-seeded-walk-1 | 正常 |
015-seeded-walk-2 | 正常 |
016-seeded-walk-3 | 正常 |
017-seeded-walk-4 | 正常 |
018-long-chain | 规模 |
019-many-parallel | 规模 |
020-max-vertices-isolated | 规模 |
运行与评分
在本 Lab 目录执行:
make doctor
make run CASE=001-sample
make score未安装 Make 时,在仓库根目录执行:
pnpm lab:doctor -- labs/chapter-07/exercise/E-07-05-seven-bridges
pnpm lab:run -- labs/chapter-07/exercise/E-07-05-seven-bridges --case 001-sample
pnpm lab:score -- labs/chapter-07/exercise/E-07-05-seven-bridges解题思路
先统计奇度顶点并检查非孤立部分连通,再按规则选择起点。使用带独立编号的边运行 Hierholzer:沿未使用边深入,回溯时把顶点加入路径,最后反转路径。
复杂度分析
排序 O(m log(m+1)),每条边仅使用一次,构造 O(n+m),空间 O(n+m)。
完成清单
思考与复盘
- 本题最容易遗漏的约束是什么?
参考思路
必须按边编号标记使用状态;只标记顶点或把平行桥合并会漏边。
- Hierholzer 回溯时为什么要把顶点加入路径,最后再整体反转?如果直接在第一次到达顶点时加入,会漏掉什么情况?
参考思路
新环可能从已经访问过的顶点接出,必须先走完当前顶点的所有边,再在回溯阶段拼接子环。回溯得到的是逆序路线,最后反转才能得到正向路径。