当前位置: 首页 > news >正文

欧拉回路与哈密尔顿回路: Fleury算法与Hierholzer 算法(C++)

图论中的回路是指一个路径, 它从某个顶点开始, 经过所有边恰好一次, 并回到起始顶点.

定义

  • 欧拉回路: 从一个顶点出发, 经过每条边恰好一次, 并且最终回到起始顶点.

  • 哈密尔顿回路: 从一个顶点出发, 经过每个顶点恰好一次, 并且最终回到起始顶点.

  • 欧拉路径: 从一个顶点出发, 访问图中的每一个边恰好一次, 但不需要回到起始顶点.

  • 哈密尔顿路径: 从一个顶点出发, 访问图中的每一个其他顶点恰好一次, 但不需要回到起始顶点.

sample

欧拉回路

无向图的条件

  • 对于无向图, 构成欧拉回路的充要条件是: 所有顶点的度数都必须是偶数.
  • 如果仅有两个顶点的度数为奇数, 则存在从其中一个顶点到另一个顶点的欧拉路径, 但不是欧拉回路.

柯尼斯堡

欧拉证明七桥问题没有解, 因为存在度为奇数的顶点.

有向图的条件

  • 对于有向图, 每个顶点的入度必须等于出度才能构成欧拉回路.
  • 如果仅有一个顶点的出度比入度多 1, 且另一个顶点的入度比出度多 1, 其余顶点的出入度相等, 则存在从出度多 1 的顶点到入度多 1 的顶点的欧拉路径.

求解算法

求解欧拉回路的主要算法包括 Fleury 算法和 Hierholzer 算法:

Fleury 算法解析

Fleury 算法是一种较为直观的方法, 逐步构造欧拉回路, 但其效率较低, 因为需要检查每一步是否会破坏图的连通性.

算法步骤如下:

  1. 选择起点:

    • 如果图中存在欧拉回路, 则可以从任意顶点开始.
    • 如果图中只存在欧拉路径, 则必须从度数为奇数的两个顶点之一开始.
  2. 遍历边:

    • 从当前顶点出发, 选择下一条边进行遍历.
    • 除非没有其他选择, 不然需要避免选择"桥"(或者说割边). 判断某条边是否为桥梁可以通过暂时移除该边并检查图是否仍然连通来实现. 加入断开了这条边之后, 原先的图不再相连, 则此边是一个桥.
  3. 标记已访问的边: 每次选择一条边后, 将其标记为已访问, 并将其从图中移除(或者记录下来以便后续恢复).

  4. 移动到下一个顶点: 移动到所选边的另一端点, 并重复上述过程, 直到所有边都被访问过.

  5. 返回起点:

    • 如果是从欧拉回路的起点开始, 则最终会回到该起点, 形成一个闭合回路.
    • 如果是从欧拉路径的一个端点开始, 则最终会到达另一个端点, 形成一条欧拉路径.
示例

求下图的欧拉路径:

sample

fleury 算法步骤:

  1. 任意选定起点, 假定选择了A., A有两条边, 均不是桥, 任选一个都可以. 假定我们选择了A-B. 此时结果如下:

    f1

  2. 此时我们到达了B, B的的三条边均不是桥, 任选其一. 假定选了B-E. 结果如下:

    f2

  3. 此时我们到达了E, 三条边均可选 假定选了E-D. 结果如下:

    f3

  4. 现在到达了D, 注意D-A是一个桥, 因为此时还有其他边可选, 所不能选D-A.

    f4

  5. 后续步骤不再赘述, 看 gif.

    fig

Hierholzer 算法

Hierholzer 算法是一个更为高效的方法, 通过利用回路合并的思想来构建欧拉回路. 它的基本思想是从任意一个顶点开始, 尝试访问每一条边, 并将访问过的边移除, 直到无法继续前进时, 再回溯寻找新的未访问边, 直到所有的边都被访问过为止.

算法步骤
  1. 选择起点:

    • 从任意一个顶点开始(对于欧拉回路, 任何顶点都可以作为起点; 对于欧拉路径, 则需要从度数为奇数的顶点之一开始).
  2. 初始化路径:

    • 创建一个空列表 path 来存储当前找到的路径.
    • 创建一个栈 stack 并将起点压入栈中.
  3. 遍历边:

    • 当栈不为空时, 执行以下操作:
      1. 弹出栈顶元素: 将栈顶元素取出并设为当前顶点 current_vertex.
      2. 检查相邻边: 检查当前顶点的所有未访问过的相邻边.
      3. 如果存在未访问的边:
        • 随机选择一条未访问的边, 并将其标记为已访问.
        • 将该边的另一端点推入栈中.
      4. 如果没有未访问的边:
        • 将当前顶点添加到 path 列表中.
  4. 合并路径:

    • 当栈为空时, path 列表中的顶点顺序即为所求的欧拉回路. 但由于我们是从后往前添加顶点的, 因此需要反转 path 列表.
  5. 返回结果:

    • 返回反转后的 path 列表, 这就是所求的欧拉回路.
示例演示

针对上题中提到的样例, hierholzer 的步骤如下图所示:

h

需要注意的是:

  1. A被第二次访问的时候, 此时没有其他边可走, 因此需要从栈中弹出A并添加到path中.
  2. 接下来的出栈操作在所有节点访问完毕的时候.
代码实现

以下是一个具体的 C++ 实现的核心部分, 完整代码请参考:

std::vector<int> FindEulerCircuit(int start) {std::stack<int> stack;  // 当前路径std::vector<int> path;  // 存储最终的欧拉回路stack.push(start);while (!stack.empty()) {int currV = stack.top();// 如果当前顶点有未访问的边auto adjList = graph_.Adj(currV);if (!adjList.empty()) {int nextV = *adjList.begin();graph_.RemoveEdge(currV, nextV);stack.push(nextV);} else {// 如果没有未访问的边,则将当前顶点加入电路path.push_back(currV);stack.pop();}}// 反转电路以获得正确的顺序std::reverse(path.begin(), path.end());return path;
}

完整代码请参考: Hierholzer.ixx

时间复杂度

Hierholzer 算法的时间复杂度为 O ( E ) O(E) O(E), 其中 E E E 是图中的边数. 这是因为每条边只会被访问一次, 并且在每次访问时只需要常数时间的操作(如栈操作和边的删除). 这使得 Hierholzer 算法在处理大规模图时非常高效.

汉密尔顿回路

寻找一个给定图是否存在哈密尔顿回路的问题是一个典型的 NP 完全问题, 这意味着目前没有已知的有效算法可以在多项式时间内解决任意图的这个问题. 通常采用的方法包括暴力搜索, 回溯法以及一些启发式的优化策略来尝试解决特定实例的问题.

由于其复杂性, 对于较大的图, 求解哈密尔顿回路往往需要消耗大量的计算资源. 然而, 在某些特殊情况下, 如图具有特定结构时, 可以设计出有效的算法来解决问题. 例如, 在竞赛编程或者算法面试中, 如果图的规模较小(比如不超过 30 个顶点), 可以通过状态压缩动态规划等方法来尝试解决.

相关文章:

欧拉回路与哈密尔顿回路: Fleury算法与Hierholzer 算法(C++)

图论中的回路是指一个路径, 它从某个顶点开始, 经过所有边恰好一次, 并回到起始顶点. 定义 欧拉回路: 从一个顶点出发, 经过每条边恰好一次, 并且最终回到起始顶点. 哈密尔顿回路: 从一个顶点出发, 经过每个顶点恰好一次, 并且最终回到起始顶点. 欧拉路径: 从一个顶点出发, …...

JavaSE学习笔记26-集合(Collection)

集合 Java 中的集合&#xff08;Collection&#xff09;是 Java 标准库中非常重要的一部分&#xff0c;用于存储和操作一组对象。Java 集合框架&#xff08;Java Collections Framework&#xff09;提供了一套丰富的接口和类&#xff0c;用于处理各种数据结构&#xff0c;如列…...

本地开发用ASP.NET Core Web API项目创建及测试

1. 服务端代码&#xff08;C#&#xff09; 1.1 创建ASP.NET Core Web API项目 打开Visual Studio 2022。 选择“创建新项目”。 选择“ASP.NET Core Web API”模板&#xff0c;点击“下一步”。 输入项目名称&#xff08;如OracleApi&#xff09;&#xff0c;选择项目位置&…...

Redis——用户签到BitMap,UV统计

目录 BitMap 使用场景 1. 用户签到系统 2. 用户行为标记 3. 布隆过滤器&#xff08;Bloom Filter&#xff09; BitMap介绍 Redis中的使用 Redis功能示例 添加&#xff1a; 获取&#xff1a; 批量获取&#xff1a; java中实现 统计本月连续签到次数 UV统计 UV 统计…...

一文详解U盘启动UEFI/Legacy方式以及GPT/MBR关系

对于装系统的老手而说一直想研究一下装系统的原理&#xff0c;以及面对一些问题时的解决思路&#xff0c;故对以前的方法进行原理上的解释&#xff0c;主要想理解其底层原理。 引导模式 MBR分区可以同时支持UEFI和Legacy引导&#xff0c;我们可以看一下微pe制作的启动盘&#…...

Unity Shader 学习13:屏幕后处理 - 使用高斯模糊的Bloom辉光效果

目录 一、基本的后处理流程 - 以将画面转化为灰度图为例 1. C#调用shader 2. Shader实现效果 二、Bloom辉光效果 1. 主要变量 2. Shader效果 &#xff08;1&#xff09;提取较亮区域 - pass1 &#xff08;2&#xff09;高斯模糊 - pass2&3 &#xff08;3&#xff…...

小迪安全-24天-文件管理,显示上传,黑白名单,访问控制

上节课回顾&#xff0c;token问题 没有更新token值&#xff0c;造成了复用 加上这段代码就好了&#xff0c;就不会复用了 文件管理-文件上传 upload.html文件&#xff0c;找ai生成就行 uoload.php接受文件上传的信息 这里在写个临时文件存储换个地方 因为上面临时文件存在c盘…...

java23种设计模式-建造者模式

建造者模式&#xff08;Builder Pattern&#xff09;学习笔记 1. 模式定义 建造者模式是一种创建型设计模式&#xff0c;通过分步构建复杂对象的方式&#xff0c;将对象的构建过程与表示分离。允许使用相同的构建过程创建不同的对象表示。 2. 适用场景 ✅ 需要创建包含多个…...

JMeter 中实现 100 个用户在 3 秒内并发登录

在 JMeter 中实现 100 个用户在 3 秒内并发登录,需要合理配置线程组、定时器和测试逻辑。以下是具体步骤: 1. 创建测试计划 打开 JMeter。右键点击“Test Plan”,选择 Add > Threads (Users) > Thread Group。 : 设置为 100(模拟 100 个用户)。 : 设置为 3...

SOME/IP-SD -- 协议英文原文讲解2

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 5.1.2.2 S…...

IntelliJ IDEA中Maven配置全指南

一、环境准备与基础配置 1.1 Windows 环境下载并配置 Maven 见此篇博文&#xff1a;环境配置 1.2 IDEA配置步骤 打开设置面板&#xff1a;File → Settings → Build → Build Tools → Maven 关键配置项&#xff1a; Maven home path E:\apache-maven-3.9.9 &#xff08;…...

第438场周赛:判断操作后字符串中的数字是否相等、提取至多 K 个元素的最大总和、判断操作后字符串中的数字是否相等 Ⅱ、正方形上的点之间的最大距离

Q1、判断操作后字符串中的数字是否相等 1、题目描述 给你一个由数字组成的字符串 s 。重复执行以下操作&#xff0c;直到字符串恰好包含 两个 数字&#xff1a; 从第一个数字开始&#xff0c;对于 s 中的每一对连续数字&#xff0c;计算这两个数字的和 模 10。用计算得到的新…...

20-R 绘图 - 饼图

R 绘图 - 饼图 R 语言提供来大量的库来实现绘图功能。 饼图&#xff0c;或称饼状图&#xff0c;是一个划分为几个扇形的圆形统计图表&#xff0c;用于描述量、频率或百分比之间的相对关系。 R 语言使用 pie() 函数来实现饼图&#xff0c;语法格式如下&#xff1a; pie(x, l…...

【LLM】R1复现项目(SimpleRL、OpenR1、LogitRL、TinyZero)持续更新

note &#xff08;1&#xff09;未来的工作需亟待解决&#xff1a; 支持大规模 RL 训练&#xff08;PPO、GRPO 等&#xff09;的开源基础框架用于稳定训练的 GRPO 训练超参的自动化调优RL 训练数据的配比&#xff08;难度、领域、任务等&#xff09;基于 Instruct 模型训练 R…...

Linux 内核网络设备驱动编程:私有协议支持

一、struct net_device的通用性与私有协议的使用 struct net_device是Linux内核中用于描述网络设备的核心数据结构,它不仅限于TCP/IP协议,还可以用于支持各种类型的网络协议,包括私有协议。其原因如下: 协议无关性:struct net_device的设计是通用的,它本身并不依赖于任何…...

20241130 RocketMQ本机安装与SpringBoot整合

目录 一、RocketMQ简介 ???1.1、核心概念 ???1.2、应用场景 ???1.3、架构设计 2、RocketMQ Server安装 3、RocketMQ可视化控制台安装与使用 4、SpringBoot整合RocketMQ实现消息发送和接收? ? ? ? ? 4.1、添加maven依赖 ???4.2、yaml配置 ???4.3、…...

FFmpeg进化论:从av_register_all手动注册到编译期自动加载的技术跃迁

介绍 音视频开发都知道 FFmpeg,因此对 av_register_all 这个 API 都很熟悉,但ffmpeg 4.0 版本开始就已经废弃了,是旧版本中用于全局初始化的重要接口。 基本功能 核心作用:av_register_all() 用于注册所有封装器(muxer)、解封装器(demuxer)和协议处理器(protocol),…...

Http升级为Https - 开发/测试服环境

1.应用场景 主要用于开发/测试服环境将http升级为https, 防止前端web(浏览器)出现Mixed Content报错; 2.学习/操作 1.文档阅读 deepseek 问答; 2.整理输出 报错信息: Mixed Content: The page at <URL> was loaded over HTTPS, but requested an insecure XMLHttpRequ…...

C语言预编译

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一、预处理的作用与流程&#xf…...

算法刷题-字符串-151.反转单词

题目 给一串字符串&#xff0c;里面有若干单词&#xff0c;以空格界定单词的结束&#xff0c;翻转其中的单词 输入&#xff1a;s " hello world " 输出&#xff1a;“world hello” 需要注意的是&#xff0c;给定的字符串可能存在头空格、尾空格以及中间的空格数量…...

Agent 能实现企业 IT 运维流程自动化吗?深度解析2026年AI Agent在运维领域的规模化落地

站在2026年4月的技术节点回望&#xff0c;AI Agent&#xff08;智能体&#xff09;是否能实现企业IT运维流程自动化&#xff0c;已经从一个“技术可行性”的命题&#xff0c;演变为“规模化落地”的行业共识。随着GPT-6的正式发布以及Amazon Agent Registry等全球性智能体注册中…...

GBase 8a数据库双活容灾方案之GVR工具核心功能介绍

南大通用&#xff08;gbase database)可视化集群双活同步工具软件&#xff08;GBase Visio Rsynctool&#xff09;&#xff0c;是GBASE南大通用自主研发的、专门适用于GBase 8a MPP Cluster的集群间同步工具。通过 GVR&#xff0c;可以灵活高效的实现集群间的数据同步&#xff…...

【技术解析】潜在扩散模型(LDM)中的图像压缩:从VAE到VQ-GAN的演进之路

1. 为什么图像压缩是LDM的第一步&#xff1f; 当你第一次接触潜在扩散模型&#xff08;LDM&#xff09;时&#xff0c;可能会好奇&#xff1a;为什么要在扩散过程前先压缩图像&#xff1f;这就像搬家时先把家具拆成零件再运输——原始像素空间就像笨重的实木家具&#xff0c;而…...

告别Source Insight卡顿!用Vim + Ctags + Cscope打造Linux下丝滑的C/C++代码阅读环境

打造Linux下极致流畅的C/C代码阅读环境&#xff1a;Vim Ctags Cscope实战指南 第一次在Linux服务器上打开一个大型C项目时&#xff0c;我盯着终端里密密麻麻的代码手足无措。图形化IDE在远程桌面上的卡顿让我几乎无法工作&#xff0c;每次跳转定义都要等待数秒&#xff0c;开…...

SourceGit深度解析:3大创新功能重塑现代Git工作流

SourceGit深度解析&#xff1a;3大创新功能重塑现代Git工作流 【免费下载链接】sourcegit Windows/macOS/Linux GUI client for GIT users 项目地址: https://gitcode.com/gh_mirrors/so/sourcegit 在当今软件开发领域&#xff0c;高效的版本控制工具已成为团队协作的基…...

MHz晶体选型与电路设计全指南

1. MHz晶体在电子设计中的核心地位在现代电子系统中&#xff0c;MHz晶体就像人类心脏的起搏器&#xff0c;为数字电路提供精准的时序基准。作为ASIC、MCU和通信模块的时钟源&#xff0c;其频率精度直接决定了系统稳定性——Wi-Fi模块的20ppm误差可能导致连接中断&#xff0c;工…...

手把手教你用Python处理ConceptNet中文数据:从CSV读取到关系查询(附繁简体转换)

手把手教你用Python处理ConceptNet中文数据&#xff1a;从CSV读取到关系查询&#xff08;附繁简体转换&#xff09; 在自然语言处理领域&#xff0c;知识图谱正成为提升模型理解能力的关键工具。ConceptNet作为开放多语言知识图谱&#xff0c;其中文部分包含丰富的概念关系数据…...

如何用CausalNex进行结构学习:NO TEARS算法深度解析

如何用CausalNex进行结构学习&#xff1a;NO TEARS算法深度解析 【免费下载链接】causalnex A Python library that helps data scientists to infer causation rather than observing correlation. 项目地址: https://gitcode.com/gh_mirrors/ca/causalnex CausalNex是…...

一站式IT运维管理平台:NeatLogic ITOM 15分钟快速上手终极指南

一站式IT运维管理平台&#xff1a;NeatLogic ITOM 15分钟快速上手终极指南 【免费下载链接】neatlogic-itom-all NeatLogic is a progressive ITOM platform offering ITOM solutions for users of various types and sizes. It includes features like ITSM, CMDB, continuous…...

python lint-staged

# 聊聊 Python 项目中的 lint-staged&#xff1a;一个被低估的提效工具 在 Python 项目里&#xff0c;代码质量检查工具大家都不陌生&#xff0c;像 flake8、black、isort 这些几乎是标配。但很多人可能遇到过这样的场景&#xff1a;每次提交代码前&#xff0c;都要手动跑一遍检…...