找欧拉回路经典Hierholzer算法的简单理解(无严谨证明)
图论的基本知识:
图可以简单看成是很多点点连在一起。
每个点都是一个节点,对于这些节点:
每个节点相连的点数,也就是每个节点上相连的线的个数,被称为该节点的度。
图的类型:
- 无向图:节点对,也就是两个节点的连线是没有方向的,可以从A到B,也可以从B到A。
- 有向图:和无向图相反,两个节点之间的连线是有方向的,只能指向一侧。
Hierholzer算法:欧拉回路中找欧拉路径
[!NOTE]
本篇目前对Hierholzer算法的解释和实现都在无向图中
了解欧拉回路
欧拉回路:
如果以一条路径走过一个图经过了所有的边且没有重复,那么就称这条路径为欧拉回路。简单点可以理解成这个图可以被一笔画成,毕竟一笔画不能倒回去。
存在欧拉回路的充分条件:如果这个图里所有的节点的度都是偶数,那么就一定存在欧拉回路,如果任何一个节点的度是奇数,那么不存在欧拉回路。以下是一个例子:
你可以选择任意陆地为起点,问你在每座桥必须而且只能通行一次的前提下能不能走过(到过即可,不限方向,)每一块陆地。
这是著名的戈尼斯堡七桥问题,答案是不可以,你可以通过前面欧拉回路的存在定理进行证明,但我们缺乏一个直观的通俗的解释。为了知道原理,让我们把这个问题抽象成如下图:
在这个图中D点的度数为3,也就是说D只有三条相连的路可以走。
现在思考:如果你想经过一个点(也即有进有出),而且不能走重复边,那么这个点最少要有两个可以走的相连的路:一个用来进入一个用来出去。同样不难想到如果一个点只有奇数个度,那么你最后一次进入这个点的时候会被困在里面,也就出不去了。如果是起点有奇数条边相连,那么最后一次出点的时候就没有路能回到起点了。
通过这种想象,我们可以感性地证明每一个节点的度数都必须是偶数才存在欧拉回路。
下图展示了一个简单的具有欧拉回路的图。你可以尝试画出路径,并感受一下为什么Hierholzer算法又被称为套圈法,这样用点连接的两个环路可以由任意欧拉回路路径抽象而出(随后证明)。
再考虑以下图,找从1出发的欧拉回路:
很容易我们就能找到两条路径:
这两条路径都可以重画为:
在这张图里有(2、4、5)(5、6、3)(1、2、3)三个圈((5,2,3)是被三个圈围成的),所以从这张图里可以比较直观的感受到找欧拉回路其实就是把所有的圈
都找到,那么我们如何去找圈呢?
假设我们走的路线为1----2----3----1,还有两个圈没有被找到,而这些圈是在<1----2----3----1>沿途的,那么我们就倒回去发现在2处有一个圈,把路线改成<1----2----4----5----2----3----1>
同理回到3加上圈变成<1----2----4----5----2----3----5----6----3----1>,与我给出的第一条路线完全一致。
而这种回溯是通过DFS,也就是深度搜索实现的。这部分的实现全看个人对图问题coding能力和技巧,可以用pair建图,也可以使用链式前向星,对于最后的路线,用栈实现后再倒序输出即可,这里入栈时机考察对递归序的理解。
使用邻边表的代码实现如下:核心只有dfs函数
#include <bits/stdc++.h>
using namespace std;
#define MAXN 10005
int n, b[10], tot = 0;
vector <pair<int, int>> graph[MAXN];
bool vis[MAXN];
stack<int> res;
void add(int a, int b) {
graph[a].emplace_back(b, tot);
graph[b].emplace_back(a, tot++);
}
void dfs(int note) {
for(auto &i : graph[note]) {
if(vis[i.second]) {
continue;
}
vis[i.second] = true;
dfs(i.first);
}
res.push(note);
}
int main() {
cin >> n;
b[0] = 1;
for(int i = 1; i <= n; i++) {
b[i] = b[i - 1] + i;
}
for(int i = 0; i < n; i++) {
for(int j = 0; j <= i; j++) {
int p1 = b[i] + j, p2 = b[i + 1] + j, p3 = b[i + 1] + j + 1;
add(p1, p2);
add(p2, p3);
add(p1, p3);
}
}
dfs(1);
cout << "Yes" << endl;
while(!res.empty()) {
cout << res.top() << " ";
res.pop();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App