欧拉回路

编程入门 行业动态 更新时间:2024-10-22 13:38:21

欧拉<a href=https://www.elefans.com/category/jswz/34/1764273.html style=回路"/>

欧拉回路

欧拉回路

定义

无向连通图G=(V,E)中的一条经过所有的边的简单回路(道路)称为G的欧拉回路(道路)。

具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉通路但不具有欧拉回路的图称为半欧拉图。

定理

欧拉回路的判断较为简单,具体判断方法如下:

无向连通图G存在欧拉回路的充要条件:

G为连通图且G中各结点的度都是偶数,特别地,当G仅有两个奇度结点(度数为奇数的结点)时,G存在欧拉道路。

一些推论:

  • 当G是仅有两个奇度结点的连通图时,G的欧拉通路必以此两个结点为端点
  • 当G是无奇度结点的连通图时,G必有欧拉回路。

有向图D中存在欧拉回路的充要条件:

D为有向图,D的基图连通,并且所有顶点的出度与入度都相等,特别地若除两个顶点外,其余顶点的出度与入度都相等,而这两个顶点中一个顶点的出度与入度之差为1,另一个顶点的出度与入度之差为-1,则图D中存在欧拉道路

一些推论:

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

判断

根据定理和推论,我们可以很好的找到欧拉通路回路的判断方法,这里就给出简明的判断方法:

A.判断欧拉通路是否存在的方法

有向图:图连通,有一个结点出度比入度大1,有一个结点入度比出度大1,其余都是出度=入度。

无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。

B.判断欧拉回路是否存在的方法

有向图:图连通,所有的顶点出度=入度。

无向图:图连通,所有顶点都是偶数度。

欧拉回路的求解

fleury算法

设G为一无向欧拉图,求G中的一条欧拉回路的算法为:
1)任取G中的一个顶点v0,令P0=v0
2)假设沿Pi=v0e1v1e2…eivi走到顶点vi,按下面的方法从E(G)-{e1,e2,…,ei}中选ei+1
a)ei+1与vi相关联;
b)除非无别的边可供选择,否则ei+1不应该是Gi=G-{e1,e2,…,ei}中的桥。
3)当2)不能再进行时算法停止。
可以证明的是,当算法停止时,所得到的简单回路Pm=v0e1v1e2…emv0为G中的一条欧拉回路。
桥:
设无向图G(V,E)为连通图,若边集E1⊆E,在图G中删除E1中所有边后得到的子图是不连通的,而删除了E1的任一真子集后得到的子图是连通图,则称E1是G的一个割边集。若一条边构成一个割边集,则称该边为割边,或桥

例题

积木/连接问题
题目描述

一天,小明买了许多积木回家,他想把这些积木拼接在一起。每块积木有两个接口,每个接口用一个数字标记,规定只有当两块积木有相同数字标记的接口时,这两块积木才可以通过该接口拼接在一起。例如,有两块积木,接口数字分别为1,2和3,4,那么这两块积木无法拼接;若两块积木接口数字分别为1,2和2,3,那么这两块积木可以通过由数字2标记的接口拼接在一起。现在小明知道所有积木的数量和每块积木接口的数字标记,你能告诉他他可以将所有积木拼接成一个整体么?

输入格式
第一行,一个正整数 n,代表积木数量。
接下来 n 行,每行两个正整数 ai, bi,代表第 i 个积木两端开口的数值。
输出结果
输出 n 个整数表示可以所有积木可以连接在一起的方案,其中第 i 个整数表示排列在第 i 位的积木编号。(注可能有多种方案,只输出一个即可
分析
看到此题目,很自然的想法是将每一个积木视为一个节点,如果两个积木之间接口可以连接的话,可以视为这两个积木之间存在着一条路径,但是,这样抽象之后,题中所要求在构建的图中就应该是可以遍历所有节点的一条道路,但是在不断连接的过程中,会出现许多麻烦,比如,(2 5),(4 2),(5 3),(4 4),(4 4)这五个积木,括号内为对应接口数值,显然因为积木(4 4)有两个,对它的处理就比较困难,所以这种建模仍旧很难求。
仍旧是这组数据:(2 5),(4 2),(5 3),(4 4),(4 4)这五个积木,括号内为对应接口数值,显然五个积木可以拼接到一块儿,拼接方式为:
(3 5)(5 2)(2 4)(4 4)(4 4)
上面我们将各个积木视为节点,能够连接视为存在一条边,但是并不有效,那么不妨换个思路,将各个积木视为边,这么一来,积木两边接口之间的数字才是节点,顺着这个思路下去,只要这个存在接口值为(a b)的积木,a,b两个节点就存在一条边,这样一来,题中所求的就是可以遍历图中所有边的一条欧拉路径,而且一个积木用过后只需对此边进行标记后。

之后按照fleury算法即可求出其中的一条欧拉道路,相应的c++实现如下:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n, ma = 0, mi = 1000;
int a[150][150], du[150], sta[1500];//a存贮图的邻接矩阵,du存储每个节点的度,sta存储最后的顺序
int top = 0;
struct node{int anum,bnum;bool visited;
}edge[1500];void dfs(int x)//dfs寻找一欧拉道路
{for (int i = mi; i <= ma; i++)if (a[i][x]){a[i][x]--;a[x][i]--;dfs(i);}sta[++top] = x;
}
int main()
{int x, y;cin >> n;for (int i = 1; i <= n; i++){cin >> x >> y;du[x]++;du[y]++;//统计每个节点的出现次数a[x][y]++;a[y][x]++;//构建邻接矩阵来存储图edge[i].anum = max(x, y);edge[i].bnum = min(x, y);edge[i].visited = false;ma = max(ma, max(x, y));mi = min(mi, min(x, y));}int startnode = 0;for (int i = mi; i <= ma; i++)if (du[i] & 1)//寻找度为奇数的点,根据定理,这个一定是欧拉道路的起点{startnode = i;break;}if (!startnode)//st为假,找不到奇数度的点,则任取一个点求图的欧拉回路{for (int i = mi; i <= ma; i++){dfs(i);if (sta[1] == sta[top]) break;}}else//st为真,求欧拉道路{dfs(startnode);}//求出图的一条欧拉路径后,转化成边的形式输出for (int i = n; i > 0; i--){node path;path.anum = max(sta[i], sta[i + 1]);path.bnum = min(sta[i], sta[i + 1]);for (int j = 1; j <= n; j++){if ((!edge[j].visited)&&(path.anum==edge[j].anum)&&(path.bnum==edge[j].bnum)){cout << j << ' ';edge[j].visited = true;break;}}}//system("pause");return 0;
}

更多推荐

欧拉回路

本文发布于:2024-03-08 22:03:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1722563.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:回路   欧拉

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!