欧拉回路、欧拉通路、欧拉图、半欧拉图等有关欧拉图的讲解与代码实现

2023-11-07

  有人说,图论的起源,就是源于欧拉图(千万别看成柏拉图)——题记


首先,先要讲一些有必要知道的东西:当然,我在这里也写过,这里再给出一些拓展的内容

欧拉通路: 通过图中每条边且只通过一次,并且经过每一顶点的通路

欧拉回路: 通过图中每条边且只通过一次,并且经过每一顶点的回路

有向图的基图:忽略有向图所有边的方向,得到的无向图称为该有向图的基图。 

欧拉图与半欧拉图

  • 欧拉图指的是给出的图G<V, E>,满足所有的点V联通,并且每个点的度都是偶数,则图中的所有的边都可以一笔画经过,并且回到起始点,则我们说给出的图G是欧拉图;
  • 半欧拉图的性质与欧拉图相似,但是它可以首尾不相连接,也就是这幅图是欧拉通路,满足图中的所有的边都可以一笔画经过,但是不要求回归起点。

无向图的欧拉图判定与有向图的欧拉图判定

无向图

  设G是连通无向图,则称经过G的每条边一次并且仅一次的路径为欧拉通路;

  如果欧拉通路是回路(起点和终点是同一个顶点),则称此回路是欧拉回路

  具有欧拉回路的无向图G成为欧拉图

有向图

(1)设D是有向图,D的基图连通,则称经过D的每条边一次并且仅有一次的有向路径为 有向欧拉通路

(2)如果有向欧拉通路是有向回路,则称此有向回路为  有向欧拉回路

(3)具有有向欧拉回路的图D称为有向欧拉图

定理(无向图)

 无向图G存在欧拉通路的充要条件是:G为连通图,并且G仅有两个奇度结点(度数为奇数的顶点)或者无奇度结点。

推论(无向图)

(1) 当G是仅有两个奇度结点的连通图时,G的欧拉通路必以此两个结点为端点;

(2)当G是无奇度结点的连通图时,G必有欧拉回路

(3)G为欧拉图(存在欧拉回路)的充分必要条件是  G为无奇度结点的连通图

定理(有向图)

有向图D存在欧拉通路的充要条件是:D为有向图,D的基图连通,并且所有顶点的出度与入度相等;或者  除两个顶点外,其余顶点的出度与入度都相等,而这两个顶点中一个顶点的出度与入度之差为1,另一个顶点的出度与入度之差为-1.

推论(有向图)

(1)当D除出、入度之差为1,-1的两个顶点之外,其余顶点的出度与入度相等时,D的有向欧拉通路必以出、入度之差为1的顶点作为始点,以出、入度之差为-1的顶点作为终点。

(2)当D的所有顶点的出、入度都相等时,D中存在有向欧拉回路。

(3)有向图D为有向欧拉图的充要条件是  D的基图为连通图,并且所有顶点的出、入度都相等。
 


欧拉图(半欧拉图)的路径求解

先举例一张图:

  我们直接从图上来看,我们正确的跑法肯定是“3--1--2--3--4--5--6--4”或者是“4--6--5--4--3--2--1--3”等等很多种方案,我分别列举了输出字典序最小与最大的情况。

  这样的话,我们可以直接dfs,我们直接找到一个起点并且往下跑。但是,这可能存在一个问题,譬如说我们的3号结点,这次想直接跑4号结点,那样就会产生最坏的情况。所以,这告诉了我们如果没有其他路径,最好不要去跑桥(3--4这条边就是桥)。

  我们这里用的是dfs深搜来解决这个问题,这里是dfs加上栈的维护,相当于是起到了一个“修复”的作用。我们这次从3往4号结点跑,因为会回溯回来再重新跑(相当于是更正修复),所以dfs搜到的是“3--4--5--6--4--(回溯)--1--2--3”此时我们的栈会变成:从栈底往栈顶来看“4 6 5 4 3 2 1 3”。此时,就是正确的欧拉通路了。

dfs的函数过程是:

    void dfs(int u)
    {
        for(int i=head[u], v; ~i; i=edge[i].nex)
        {
            if(vis[i]) continue;
            vis[i] = true;
            v = edge[i].to;
            dfs(v);
        }
        Stap[++Stop] = u;
    }

当然,这个剪枝,虽然是用了vis剪枝了,但是由于每条边只用一次,我们可以用一种叫做当前弧优化的东西来剪枝(可以参考Dinic的当前弧优化来解决这个问题)。

void dfs(int u)
{
    for(int i=head[u], v; ~i; i=head[u])
    {
        v = edge[i].to; head[u] = edge[head[u]].nex;
        dfs(v);
    }
    Stap[++Stop] = u;
}

接下去,换一种比较简短的写法,与上面这个作用一样:

void dfs(int u)
{
    while(~head[u])
    {
        v = edge[i].to; head[u] = edge[head[u]].nex;
        dfs(v);
    }
    Stap[++Stop] = u;
}

放一道判断是否是欧拉回路的题:

欧拉回路

 HDU - 1878

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
//#define INF 10000007.
#define eps 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e3 + 7;
int N, M, du[maxN], root[maxN];
int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
inline void init()
{
    for(int i=1; i<=N; i++)
    {
        du[i] = 0;
        root[i] = i;
    }
}
int main()
{
    while(scanf("%d", &N) && N)
    {
        scanf("%d", &M);
        init();
        for(int i=1, u, v, fu, fv; i<=M; i++)
        {
            scanf("%d%d", &u, &v);
            du[u]++; du[v]++;
            fu = fid(u); fv = fid(v);
            if(fu ^ fv) { root[fu] = fv; }
        }
        bool ok = true; int cnt = 0;
        for(int i=1; i<=N; i++)
        {
            if(i == fid(i))
            {
                cnt++;
                if(cnt > 1)
                {
                    ok = false;
                    break;
                }
            }
            if(du[i] & 1) { ok = false; break; }
        }
        printf("%d\n", ok);
    }
    return 0;
}

再放一道输出欧拉回路路径的题:

Watchcow

 POJ - 2230

给出N个点,M条边,并且呢,M条边要经过两次,一次是从u到v,那么下一次就不能走u到v了,只允许走v到u了。

其实题意已经帮你把欧拉图建好了,而且题目保证联通。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
//#define INF 10000007.
#define eps 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e4 + 7, maxM = 5e4 + 7;
int N, M;
struct LSQXX
{
    int head[maxN], cnt;
    struct Eddge
    {
        int nex, to;
        Eddge(int a=-1, int b=0):nex(a), to(b) {}
    }edge[maxM << 1];
    inline void addEddge(int u, int v)
    {
        edge[cnt] = Eddge(head[u], v);
        head[u] = cnt++;
    }
    inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
    int Stap[maxM << 1], Stop;
    void dfs(int u)
    {
        int v;
        while(~head[u])
        {
            v = edge[head[u]].to;
            head[u] = edge[head[u]].nex;
            dfs(v);
        }
        Stap[++Stop] = u;
    }
    inline void clear()
    {
        cnt = 0; Stop = 0;
        for(int i=1; i<=N; i++) head[i] = -1;
    }
} E;
struct Graph
{
    int u, v;
    Graph(int a=0, int b=0):u(a), v(b) {}
    inline void In_Put() { scanf("%d%d", &u, &v); }
} G[maxM];
int main()
{
    scanf("%d%d", &N, &M);
    E.clear();
    for(int i=1; i<=M; i++) { G[i].In_Put(); E._add(G[i].u, G[i].v); }
    E.dfs(1);
    for(int i=E.Stop; i; i--) printf("%d\n", E.Stap[i]);
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

欧拉回路、欧拉通路、欧拉图、半欧拉图等有关欧拉图的讲解与代码实现 的相关文章

  • 东北大学acm训练第五周

    include
  • Connections between cities 【HDU - 2874】【在线LCA算法】

    题目链接 昨天刚学了在线LCA 今天就来硬刚这道题还是花了一整天的时间 不过对于LCA却有了更多的理解 这道题在讲述不同根的做法上尤其是很好的 题目告诉我们有N个节点和M条边 以及C次询问 每次查询的是 L R 这两个节点间的距离 还是算得
  • 欧拉回路【总结】【题解】

    题目 欧拉回路 UOJ 欧拉回路 Liuser s OJ 题目描述 有一天一位灵魂画师画了一张图 现在要你找出欧拉回路 即在图中找一个环使得每条边都在环上出现恰好一次 一共两个子任务 无向图 有向图 输入格式 第一行一个整数 t 表示子任务
  • LeetCode-Python-1584. 连接所有点的最小费用(MST)

    给你一个points 数组 表示 2D 平面上的一些点 其中 points i xi yi 连接点 xi yi 和点 xj yj 的费用为它们之间的 曼哈顿距离 xi xj yi yj 其中 val 表示 val 的绝对值 请你返回将所有点
  • UVA-1601 万圣节后的早晨 题解答案代码 算法竞赛入门经典第二版

    GitHub jzplp aoapc UVA Answer 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 以三个点的当前位置作为状态 广度优先遍历 找到终点即为最短次数 注意 一次可以移动多个点 但是每个点只能移动一步 在同一次中 B可
  • 【算法学习笔记】19:拓扑排序

    1 简述 计算拓扑序列的一个方式是 用BFS来尝试访问所有的节点 但是有一个约束就是只有入度为 0 0 0的节点才能被加入到扩展队列里 每次从队列里取出一个节点 也就同时在图中将这个节点拆除 所以它的所有后继的节点都减少 1 1 1 如果已
  • 【构造】0617 Edge Split

    题意 给定一个 n n n 点 m m m 条边的无向连通图 其中 1
  • XYZZY 【POJ - 1932】【SPFA】

    题目链接 有N个点 然后输入1 N个点 输入从它到其他点的血量变化 然后有几个点能到达 最后是这几个点 我们起点为1 终点为N 然后求的是我们是不是有可能或者达到终点 gt 0 直接SPFA跑最长路 感觉是在造样例 6 0 1 2 1000
  • 数据结构 图的应用

    文章目录 生成树 定义 性质 带权图的最小生成树 最小生成树的生成规则 最小生成树 Kruskal算法 步骤 最小生成树 Prim算法 步骤 最短路径 非负权值的单源最短路径 Dijkstra算法 目的 算法 存储空间 算法步骤 算法实现
  • 图论17(Leetcode864.获取所有钥匙的最短路径)

    用二进制表示获得的钥匙 假设n 钥匙个数 000000000代表没有钥匙 0000000001代表有idx为1的钥匙 0000000011代表有idx 1 2的钥匙 这方法巧妙又复杂 代码 class Solution static int
  • 离散数学第一章总结

    离散数学第一章 1 公式类型 1 重言式 也是永真式 公式真值恒为1 2 矛盾式 永假式 真值恒为0 3 可满足式 不是矛盾式的就都是可满足式 重言式一定是可满足式 2 成真赋值与成假赋值 也叫成真指派与成假指派 一组原子的取值 真值指派
  • POJ 3259 Wormholes(最短路——Bellman-ford)

    A Wormholes While exploring his many farms Farmer John has discovered a number of amazing wormholes A wormhole is very p
  • 《算法图解》读书笔记(二)

    第六章 图 广度优先搜索 1 解决最短路径问题 shortest path problem 的算法被称为广度优先搜索 breadth first search 2 图由节点 node 和边 edge 组成 一个节点可能与众多节点直接相连 这
  • 数据结构——非线性结构(图)

    文章目录 一 非线性结构的概述 二 图的基本概念 1 定义 2 无向图 有向图 2 1 无向图 2 2 有向图 2 3 简单图 2 4 多重图 3 顶点的度 出度 入度 3 1 对于无向图 3 2 对于有向图 4 边的权 带权图 网 5 点
  • 【算法笔记】Prim算法

    定义 prim算法 图论中的一种算法 可在加权连通图里搜索最小生成树 由此算法搜索到的边子集所构成的树中 不但包括了连通图里的所有顶点 并且其所有边的权值之和最小 算法描述 输入 一个加权连通图 其中顶点集合为V 边集合为E 初始化 Vne
  • Two Arithmetic Progressions

    Two Arithmetic Progressions 题目链接 题意 思路 AC代码1 include
  • 图论--最近公共祖先LCA

    最近公共祖先LCA LCA Least Common Ancestors 即最近公共祖先 是指这样一个问题 在有根树中 找出某两个结点u和v最近的公共祖先 另一种说法 离树根最远的公共祖先 最近公共祖先是相对于两个节点来说的 一般来说 最近
  • 第14届蓝桥杯C++B组省赛

    文章目录 A 日期统计 B 01 串的熵 C 冶炼金属 D 飞机降落 E 接龙数列 F 岛屿个数 G 子串简写 H 整数删除 I 景区导游 J 砍树 今年比去年难好多 Update 2023 4 10 反转了 炼金二分没写错 可以AC了 U
  • E (1052) : DS树--带权路径和

    文章目录 一 题目描述 二 输入与输出 1 输入 2 输出 三 参考代码 一 题目描述 计算一棵二叉树的带权路径总和 即求赫夫曼树的带权路径和 已知一棵二叉树的叶子权值 该二叉树的带权路径和APL等于叶子权值乘以根节点到叶子的分支数 然后求
  • 860.染色法判定二分图

    二分图是指一个图中的所有顶点可以分为两部分 并且每条边连接的是属于不同部分的两个顶点 include

随机推荐

  • eclipse转到IDEA详细步骤

    eclipse转IDEA 一 检出eclipse项目到本地 二 eclipse转IDEA过程 2 1 创建空项目 2 2 文件夹名 2 3 添加项目 2 4 下一步 2 5 下一步 2 6 下一步 2 7 下一步 2 8 OK 2 9 设置
  • web前端模仿微信悬浮窗效果

    微信新出了个悬浮窗的功能 因为业务需要 我用js写了个h5版本的 依赖jq或者zepto 可以自己选择改造 请用手机或者电脑浏览器模拟手机模式查看 在线预览 代码如下
  • 【数码管识别】需要改进的地方

    类型转换的问题 统一一种类型 该图中的问题已通过先提取感兴趣区域后图像处理解决了 图像反转的问题 需要简化
  • 云服务器建站:如何防止别人ping我们的网站?

    一 Ping功能是什么 在网络中ping是一个十分强大的TCP IP工具 它的作用主要为 1 用来检测网络的连通情况和分析网络速度 2 根据域名得到服务器IP 3 根据ping返回的TTL值来判断对方所使用的操作系统及数据包经过路由器数量
  • C++编写封装驱动接口时::符号的意思

    今天在查看mini2440官方提供的camtest c文件时 发现使用C 编写 然后便仔细分析了下代码 发现里面的open close write read等linux系统函数前面都加上了 符号 不明白什么意思 于是在网上找了下 解释如下
  • 四个步骤教你爬取网站图片,新手必学

    很多人学习Python很重要的一个原因是 可以很简单的把一个网站的数据爬下来 尤其是做我们这一行 产品经理 电商行业 领导 弄一个买卖游戏周边商品的交易APP出来 我 行 那我们卖什么呀 领导 看下友商卖什么我们就卖什么 我 好吧 那就爬点
  • redis内存数据库 笔记6:应用场景

    目录 一 网站缓存 二 实现最新消息排行 三 共同好友 一 网站缓存 1 String 字符串 2 Hash 二 实现最新消息排行 List 列表 List 说白了就是链表 redis 使用双端链表实现的 List 相信学过数据结构知识的人
  • 带你了解什么是中断以及外部中断案例分析

    了解什么是中断 好 今天我来给大家讲一下我们什么是中断以及如何去运用外部中断源 首先 我们学习单片机的时候 一定听说过学会中断才是单片机的入门 因为中断系统大大提高了单片机对随机事件的实时处理能力 并且提高了单片机的工作效率 当然 中断这个
  • 函数对象包装器(std::function、std::bind / std::placeholder)

    这部分内容虽然属于标准库的一部分 但是从本质上来看 它却增强了 C 语言运行时的能力 这部分内容也相当重要 所以放到这里来进行介绍 std function和std bind的主要用途之一是安全函数指针 网上有很多文章解释了函数指针在C C
  • 计算机原理--操作系统概览

    操作系统概览 What Why 操作系统的基本功能 操作系统相关概念 What Why 操作系统是管理计算机硬件和软件资源的计算机程序 管理配置内存 决定资源供需顺序 控制输入输出设备等 操作系统提供让用户和系统交互的操作界面 操作系统的种
  • Python 使用 shuffle() 乱序排列/打乱序列/打乱列表

    在 Python 中 列表和元组中的元素是有顺序的 但是由于元组不可变 所以一般我们涉及到打乱操作 都是针对的列表 在深度学习中 由于原始训练数据可能存在顺序性 当我们分批成 mini batch 进行学习的时候 后面的数据会对系数影响更大
  • 数据结构——循环单链表

    循环单链表是单链表的另一种形式 其结构特点链表中最后一个结点的指针域不再是结束标记 而是指向整个链表的第一个结点 从而使链表形成一个环 和单链表相同 循环链表也有带头结点结构和不带头结点结构两种 带头结点的循环单链表实现插入和删除操作较为方
  • MFC CcomboBox控件

    组合框控件简介 组合框其实就是把一个编辑框和一个列表框组合到了一起 分为三种 简易 Simple 组合框 下拉式 Dropdown 组合框和下拉列表式 Drop List 组合框 下面讲讲它们的区别 简易组合框中的列表框是一直显示的 效果如
  • 515. Find Largest Value in Each Tree Row

    You need to find the largest value in each row of a binary tree Example Input 1 3 2 5 3 9 Output 1 3 9 不明白这样的题目还是medium
  • vb 删除服务器文件,【开源】VB编写的WEB服务器,链接在2楼,原帖已删

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 定义 这是一款桌面级的WEB服务器 包含一个静态的http服务器与一个js脚本引擎 可以展示静态的网页与生成简单的动态页面 适合个人在windows服务器上面简单的建立http服务 支持情况 静
  • Unity3D 显示private变量

    显示特定的private变量 以及希望在Object Inspector中显示的并予以显式标记的变量 这类变量将在Normal和Debug模式中加以显示 对此 可利用 SerializeField 属性声明private 变量 如下所示 S
  • 在Ubuntu 14.04上安装最新版mesa

    关于 mesa mesa是一个开源的OpenGL的实现 它被广泛用于包括X Windows在内的各种渲染系统中 具体见官网 http www mesa3d org intro html 现在 我们将在Ubuntu 14 04上编译并安装最新
  • 2023年第五届河南省CCPC大学生程序设计竞赛

    Problem A 小水獭游河南 小水獭来到河南旅游 它认为一个字符串 s 是 HENAN 的当且仅当存在两个非 空 字符串 a 和 b 满 足如下三个条件 a 由小写字母组成 且 a 中每种字母只出现了一次 b 由小写字母组成 且 b 是
  • 不可多得的干货!字节跳动Android实习面试凉凉经,移动架构师成长路线

    前言 说不焦虑其实是假的 因为无论是现在还是最近几年 很早就有人察觉Android开发的野蛮生长时代已经过去 过去的优势是市场需要 这个技术少有人有 所以在抢占市场的时候 基本上满足需要就已经可以了 但是现在 各式各样的APP层出不穷 AP
  • 欧拉回路、欧拉通路、欧拉图、半欧拉图等有关欧拉图的讲解与代码实现

    有人说 图论的起源 就是源于欧拉图 千万别看成柏拉图 题记 首先 先要讲一些有必要知道的东西 当然 我在这里也写过 这里再给出一些拓展的内容 欧拉通路 通过图中每条边且只通过一次 并且经过每一顶点的通路 欧拉回路 通过图中每条边且只通过一次