【图论】欧拉回路

这篇具有很好参考价值的文章主要介绍了【图论】欧拉回路。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

你的qq密码是否在圆周率中出现?

一个有意思的编码问题:假设密码是固定位数,设有 n n n位,每位是数字0-9,那么这样最短的“圆周率”的长度是多少?或者说求一个最短的数字串定包含所有密码。

理论

一些定义:

通过图中所有边恰好一次且行遍所有顶点的通路称为欧拉通路;
通过图中所有边恰好一次且行遍所有顶点的回路称为欧拉回路;
具有欧拉回路的无向图称为欧拉图;
具有欧拉通路但不具有欧拉回路的无向图称为半欧拉图。

求欧拉回路/通路,俗称一笔画问题,之前一直以为这个问题十分困难,直到慢慢学习揭开它的真面目。在离散课程中,学习到判断(半)欧拉图的充要条件是顶点的度数满足一定条件。具体如下
【图论】欧拉回路
必要性比较容易证明,充分性是通过一个构造性证明,大致是首先找到一个回路 C C C,若回路 C C C中存在顶点 u u u有出边不在回路 C C C中,则从顶点 u u u出发dfs可以回到 u u u构成一个回路 C ′ C' C,将回路 C C C C ′ C' C合并得到一个新回路,反复操作直到所有边均访问过。

Fleury 算法

之前数学建模了解过一个Fleury算法,大意是桥不能走,个人感觉这不是≈不能走的路不能走!而且图在动态变化怎么动态地维护图中的桥,没有详细了解而且网上相关blog也比较少。
【图论】欧拉回路

Hierholzer 算法

Hierholzer 算法用于在连通图中寻找欧拉路径,其流程如下:

  • 从起点出发,进行深度优先搜索。
  • 每次沿着某条边从某个顶点移动到另外一个顶点的时候,都需要删除这条边。
  • 如果没有可移动的路径,则将所在节点加入到栈中,并返回。

证明传送门:https://taodaling.github.io/blog/2019/04/25/Hierholzer%E7%AE%97%E6%B3%95/

代码模板

  • leetcode 332:求有向图的欧拉通路,固定起点,节点用string标识,返回字典序最小的序列
  • 算法核心:访问前删除边(通常我们通过vis[]数组标记顶点已访问而不是边),并在顶点所有出边访问完后,入栈记录答案,实际上欧拉通路是递归调用返回路径构成的通路
  • 容器map嵌套priority_queue的技巧,之前自己灵光一现想到用于将数组下标拓展至负数,这里拓展为string类型,按字典序进行从小到大进行排序,但这种写法仅适用于有向图,STL优先队列没有定义erase操作
  • 时间复杂度: O ( m l o g ⁡ m ) O(mlog⁡m) O(mlogm),其中 m m m 是边的数量。对于每一条边我们需要 O ( l o g m ) O(logm) O(logm) 地删除它,最终的答案序列长度为 m + 1 m+1 m+1,而与 n n n 无关。
  • 空间复杂度: O ( m ) O(m) O(m),其中 m m m 是边的数量。我们需要存储每一条边。
unordered_map<string, 
priority_queue<string, vector<string>, std::greater<string>>> vec;

vector<string> stk;

void dfs(const string& curr) {
    while (vec.count(curr) && vec[curr].size() > 0) {
        string tmp = vec[curr].top();
        vec[curr].pop();
        dfs(tmp);
    }
    stk.emplace_back(curr);
}

vector<string> findItinerary(vector<vector<string>>& tickets) {
    for (auto& it : tickets) {
        vec[it[0]].emplace(it[1]);
    }
    dfs("JFK");
    reverse(stk.begin(), stk.end());
    return stk;
}
  • luogu P2731:求无向图的欧拉通路
  • 算法核心:访问前删除边(通常我们通过vis[]数组标记顶点已访问而不是边),并在顶点所有出边访问完后,入栈记录答案,实际上欧拉通路是递归调用返回路径构成的通路
  • 通过map<pair<int, int>, int> cnt标记边的访问,这里时间复杂度为 O ( m l o g m ) O(mlogm) O(mlogm),对cnt的自减操作实际在修改rb_tree的值,复杂度为 O ( l o g m ) O(logm) O(logm),和优先队列相同
vector<int> ans;
vector<int> g[2005];
map<pair<int, int>, int> cnt;
int m;

void dfs(int u) {
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        if (cnt[{u, v}]) {
            cnt[{u, v}]--; cnt[{v, u}]--;
            dfs(v);
        }
    }
    ans.push_back(u);
}

void Euler() {
    for (int i = 1; i <= 500; i++) {
        sort(g[i].begin(), g[i].end());
    }
    bool flag = 0;
    for (int i = 1; i <= 500; i++) {
        if (g[i].size() & 1) {
            flag = 1; dfs(i);
            break;
        }
    }
    if (!flag) {
        for (int i = 1; i <= 500; i++) {
            if (g[i].size()) {
                dfs(i);
                break;
            }
        }
    }
    reverse(ans.begin(), ans.end());
}

编码问题的解

取所有 n − 1 n-1 n1位数为节点,共 1 0 n − 1 10^{n-1} 10n1个,每个节点有10条出边和入边,设当前节点为 a 1 a 2 . . . a n − 1 a_1a_2...a_{n-1} a1a2...an1,那么它的第 r r r条出边连向节点 a 2 . . . a n − 1 r a_2...a_{n-1}r a2...an1r,这样从一个节点顺着第 r r r条边走到另一个节点,就相当于输入了数字 x x x

在节点对应的数的末尾加上某条出边的编号,就形成了一个 n n n位数,并且每个节点都能用这样的方式形成10个 n n n位数,共有 1 0 n 10^n 10n n n n位数对应所有密码,每条边映射一个密码

下图是每位只有数字0,1的情况。
【图论】欧拉回路

因此问题转化不重复地遍历所有边,即为求该图的欧拉回路,由于每个节点均有10条出边和10条入边,所以答案一定存在,这符合我们的认知,一定存在包含所有密码的数字串。文章来源地址https://www.toymoban.com/news/detail-408720.html

到了这里,关于【图论】欧拉回路的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python学习28:计算圆周率——蒙特卡洛法

    描述 ‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 蒙特卡洛(M

    2024年02月08日
    浏览(50)
  • Python中计算圆周率的n种方法

    Python中计算圆周率的n种方法 使用math库中的pi常量 使用π的计算公式:4*arctan(1) 使用级数展开公式计算π 使用蒙特卡洛方法计算π 使用高斯公式计算π(仅适用于偶数n) 使用Python的内置库mpmath进行高精度计算 使用无限级数进行π的近似计算 以上就是使用Python计算π的多种方法

    2024年04月09日
    浏览(43)
  • 用python计算圆周率PI,并显示进度条

    ‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬ 描述 用python计算圆周率PI ‪‬‪‬‪‬‪

    2024年02月05日
    浏览(42)
  • 【基础算法】圆周率的多种方法求算 & C++实现

            一个圆如下面左图所示,其半径为1,其内部内接一个正六边形。设正六边形的边长为y1。由几何知识可得知y1=1,所以圆的周长可近似为正六边形的周长C=6×y1=6.所以圆周率为前面的近似圆周长与圆直径之比,即C/2= 3 ≈π ,这就是按照割圆法来得到圆周率近似值的方

    2024年02月05日
    浏览(55)
  • 蓝桥杯专题-真题版含答案-【大衍数列】【圆周率】【分糖果】【等额本金】

    点击跳转专栏=Unity3D特效百例 点击跳转专栏=案例项目实战源码 点击跳转专栏=游戏脚本-辅助自动化 点击跳转专栏=Android控件全解手册 点击跳转专栏=Scratch编程案例 点击跳转=软考全系列 点击跳转=蓝桥系列 专注于 Android/Unity 和各种游戏开发技巧,以及 各种资源分享 (网站、

    2024年02月13日
    浏览(51)
  • 学校头歌作业3_4计算圆周率(头歌作业[Python])

    在CSDN上补充前几期的内容 第1关:割圆法 第2关:无穷级数法 第3关:蒙特卡洛法 第4关:梅钦法 第5关:拉马努金法

    2024年02月10日
    浏览(44)
  • 【人工智能的数学基础】圆周率(Ratio of Circumference to Diameter)的计算

    Ratio of circumference to diameter. 圆周率

    2024年02月07日
    浏览(56)
  • 0基础学习VR全景平台篇 第76篇:全景相机-圆周率全景相机如何直播推流

    圆周率科技,成立于2012年,是中国最早投身嵌入式全景算法研发的团队之一,亦是全球市场占有率最大的全景算法供应商。相继推出一体化智能屏、支持一键高清全景直播的智慧全景相机--Pilot Era 和Pilot One ,为用户带来实时畅享8K的高清沉浸式直播体验。 一、相机端 1、相机

    2024年02月14日
    浏览(42)
  • 欧拉路径和欧拉回路(Euler Path and Euler Circuit)解释

    欧拉路径(欧拉回路)是图论非常重要的组成部分,欧拉路径是数学家欧拉在研究著名的德国哥尼斯堡(Koenigsberg)七桥问题时发现的。这一发现直接导致了一门新的理论研究的诞生-图论问题。 欧拉路径和欧拉回路区别 在一个连通图上,如果从一个顶点出发,历经访问所有的边

    2024年02月11日
    浏览(40)
  • 图论中回路与圈的概念区分

    第一种定义方法 迹 是边不重复的通路,但是顶点可以重复。 回路 是首尾顶点相同的迹。 路 是顶点不重复的迹,即边和顶点都不重复的通路,但是首尾顶点可以相同。 圈 是首尾顶点相同的路。 第二种定义方法 回路:起点终点相同 简单通路:起点到终点所经过的 边不同 

    2024年02月04日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包