若图G中存在这样一条路径,使得它恰通过G中每条边一次,则称该路径为
欧拉路径。若该路径是一个圈,则称为
欧拉(Euler)回路。
具有欧拉回路的图称为
欧拉图(简称E图)。具有欧拉路径但不具有欧拉回路的图称为半欧拉图。
以下判断基于此图的基图连通。
无向图存在欧拉回路的充要条件
一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。
有向图存在欧拉回路的充要条件
一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。
混合图存在欧拉回路条件
要判断一个混合图G(V,E)(既有有向边又有无向边)是欧拉图,方法如下:
假设有一张图有向图G',在不论方向的情况下它与G同构。并且G'包含了G的所有有向边。那么如果存在一个图G'使得G'存在欧拉回路,那么G就存在欧拉回路。
求欧拉回路的思路:
循环的找到出发点。从某个节点开始,然后查出一个从这个出发回到这个点的环路径。这种方法不保证每个边都被遍历。如果有某个点的边没有被遍历就让这个点为起点,这条边为起始边,把它和当前的环衔接上。这样直至所有的边都被遍历。这样,整个图就被连接到一起了。
具体步骤:
1。如果此时与该点无相连的点,那么就加入路径中
2。如果该点有相连的点,那么就加入队列之中,遍历这些点,直到没有相连的点。
3。处理当前的点,删除走过的这条边,并在其相邻的点上进行同样的操作,并把删除的点加入到路径中去。
Fleury算法模板如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<limits.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<math.h>
#define maxn 1005
using namespace std;
int n,m;//n个顶点,m条边
int path[maxn][maxn];
stack<int>t;
void dfs(int x)
{
t.push(x);
for(int i=1;i<=n;i++)
{
if(path[x][i])
{
path[x][i]=path[i][x]=0;//删除此边
dfs(i);
break;
}
}
}
void Fleury(int x)
{
t.push(x);
while(!t.empty())
{
int b=0;
for(int i=1;i<=n;i++)
{
if(path[t.top()][i])
{
b=1;
break;
}
}
if(!b)
{
printf("%d ",t.top());
t.pop();
}
else
{
int y=t.top();
t.pop();
dfs(y);
}
}
printf("\n");
}
int main()
{
int i,j,x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
while(!t.empty())
t.pop();
memset(path,0,sizeof(path));
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
path[x][y]=path[y][x]=1;//无向图建边
}
int num=0,start=1;
for(i=1;i<=n;i++)
{
int degree=0;
for(j=1;j<=n;j++)
if(path[i][j])
degree++;
if(degree%2==1)
{
start=i;//如果存在奇数顶点,则从奇数顶点出发,否则从1出发
num++;
}
}
if(num==0 || num==2)
Fleury(start);
else
printf("No Euler Path\n");
}
}