怎么判断是不是欧拉回路_欧拉回路基本概念+判断+求解

1.定义

如果图G(有向图或者无向图)中所有边一次仅且一次行遍所有顶点的通路称作欧拉通路。

如果图G中所有边一次仅且一次行遍所有顶点的回路称作欧拉回路。

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

2. 定理及推论

欧拉通路和欧拉回路的判定是很简单的,请看下面的定理及推论。

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

G为连通图,并且G仅有两个奇度结点(度数为奇数的顶点)或者无奇度结点。

推论1:

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

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

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

有向图D存在欧拉通路的充要条件是:

D为有向图,D的基图连通,并且所有顶点的出度与入度都相等;或者除两个顶点外,其余顶点的出度与入度都相等,而这两个顶点中一个顶点的出度与入度之差为1,另一个顶点的出度与入度之差为-1。

推论2:

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

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

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

3.欧拉通路回路存在的判断

根据定理和推论,我们可以很好的找到欧拉通路回路的判断方法,定理和推论是来自离散数学的内容,这里就给出简明的判断方法:

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

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

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

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

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

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

4.欧拉回路的应用

A.哥尼斯堡七桥问题

B.一笔画问题

C.旋转鼓轮的设计

5.欧拉回路的求解

A.  DFS搜索求解欧拉回路

基本思路:利用欧拉定理判断出一个图存在欧拉回路或欧拉通路后,选择一个正确的起始顶点,用DFS算法遍历所有的边(每一条边只遍历一次),遇到走不通就回退。在搜索前进方向上将遍历过的边按顺序记录下来。这组边的排列就组成了一条欧拉通路或回路。

#include#include#include#include

#define MAX 2010

using namespacestd;intmaps[MAX][MAX];int in[MAX];intt[MAX];intflag;intk;intMax,Min;int DFS(intx)

{inti;for(i=Min;i<=Max;i++)

{if(maps[x][i])///从任意一个与它相连的点出发

{

maps[x][i]--;///删去遍历完的边

maps[i][x]--;

DFS(i);

}

}

t[++k]=x;///记录路径,因为是递归所有倒着记

}intmain()

{intn,i,x,y;

Max=-9999;

Min=9999;

flag=0;

scanf("%d",&n);for(i=1;i<=n;i++)

{

scanf("%d%d",&x,&y);

maps[x][y]++;

maps[y][x]++;

Max=max(x,max(y,Max));

Min=min(x,min(y,Min));in[x]++;in[y]++;

}for(i=Min;i<=Max;i++)

{if(in[i]%2)///存在奇度点,说明是欧拉通路

{

flag=1;

DFS(i);break;

}

}if(!flag)///全为偶度点,从标号最小的开始找

{

DFS(Min);

}for(i=k;i>=1;i--)

{

printf("%d\n",t[i]);

}return 0;

}

B.  Fleury(佛罗莱)算法

Fleury算法是对DFS爆搜的一种改进,使用DFS漫不经心的随意走是效率不高的,Fleury是一种有效的算法。

关键是能不走桥就不去走桥,实在无路可走了才去走桥!!!

#include #include#include#include#include

using namespacestd;int ans[200];inttop;intN,M;int mp[200][200];void dfs(intx)

{inti;

top++;

ans[top]=x;for (i=1; i<=N; i++)

{if(mp[x][i]>0)

{

mp[x][i]=mp[i][x]=0;///删除此边

dfs(i);break;

}

}

}void fleury(intx)

{intbrige,i;

top=1;

ans[top]=x;///将起点放入Euler路径中

while(top>=0)

{

brige=0;for (i=1; i<=N; i++) ///试图搜索一条边不是割边(桥)

{if(mp[ans[top]][i]>0)///存在一条可以扩展的边

{

brige=1;break;

}

}if (!brige)///如果没有点可以扩展,输出并出栈

{

printf("%d", ans[top]);

top--;

}else ///否则继续搜索欧拉路径

{

top--;///为了回溯

dfs(ans[top+1]);

}

}

}intmain()

{intx,y,deg,num,start,i,j;

scanf("%d%d",&N,&M);

memset(mp,0,sizeof(mp));for(i=1;i<=M; i++)

{

scanf("%d%d",&x,&y);

mp[x][y]=1;

mp[y][x]=1;

}

num=0;

start=1;///这里初始化为1

for(i=1; i<=N; i++)

{

deg=0;for(j=1; j<=N; j++)

{

deg+=mp[i][j];

}if(deg%2==1)///奇度顶点

{

start=i;

num++;

}

}if(num==0||num==2)

{

fleury(start);

}else{

puts("No Euler path");

}return 0;

}

你可能感兴趣的:(怎么判断是不是欧拉回路)