若一个图为欧拉图或半欧拉图都可以通过一笔画遍历。
通过图(有向图或无向图)中的所有边且每一条边仅通过一次的通路称为欧拉通路,若此通路为回路则称为欧拉回路。
具有欧拉回路的图称为欧拉图,具有欧拉通路而无欧拉回路的图称为半欧拉图。
无向图:
无向图G是欧拉图:当且仅当G是连通的且没有奇度顶点。
无向图G是半欧拉图:当且仅当G是连通的且恰有两个奇度顶点。
若图G中存在这样一条路径,使得它恰通过G中每条边一次,则称该路径为欧拉路径。若该路径是一个圈,则称为欧拉(Euler)回路。
欧拉回路问题可以分为无向图中的欧拉回路和欧拉通路,有向图中的欧拉回路和欧拉通路。这几个问题大抵相像。
有向欧拉回路有:
定理:假设有像多重图D有性质:当忽略有向边上的方向时,得到的图是连通的,那么D有有向欧拉回路当且仅当D的每个顶点的入度和出度相等。
类似的,对有向欧拉通路有:
定理:D有有向欧拉通路,当且仅当除两个不同顶点B和C之外,D的其它顶点的入度和出度相等,且B的出度比入度大1,C的入度比出度大1。在这种情况下,有向欧拉通路自B出发,至C终止。
由上面的定理可以知道,如果要判断一个有向图的欧拉回路是否存在,需要先判断连通性,再判断出度入度。对于无向图,判断方法类似。
判断连通性可以通过DFS或者并查集来实现。
欧拉定理 如果一个网络是连通的并且奇顶点的个数等于0或2,那么它可以一笔画出;否则它不可以一笔画出。
判断一笔画的方法:
①是连通的。一个图,如果图上任意二点总有线段连接着,就称为连通的。不是连通的就不能一笔画出。
②奇点个数是0或者是2。图上线段的端点可以分成二类,奇点和偶数。一个点,以它为端点的线段数是奇数就称为奇点,线段数是偶数就称为偶点。
一个图是否是一笔画就看奇点的个数,奇点个数是 0 或者 2,就是一笔画,否则就不是一笔画。
所以这个问题完全可以转化策略为:
第一步: 首先我们不管它三七二十几,先进行连通性的判断。
第二步:
(1)如果是连通的,我们来判断此图的度的奇点的个数是0或者是2 ,如果是,则说明这个是欧拉图,即可以一笔画出,反之则不能一笔画出
(2)如果是非连通的,这说明这个图很定不能一笔画出。
#include
#include
using namespace std;
int mp[1010][1010];
int n,p,q,a,b;
short vis[1010],c[1010];
void dfs(int cur)
{
vis[cur]=1;
for(int i=1;i<=p;i++)
{
if(mp[cur][i]&&!vis[i])
{
dfs(i);
}
}
}
int main()
{
scanf("%d",&n);
while(n--)
{
memset(mp,0,sizeof(mp));
memset(vis,0,sizeof(vis));
memset(c,0,sizeof(c));
scanf("%d%d",&p,&q);
for(int i=0;i
Fleury(佛罗莱)算法求欧拉回路的学习
#include
#include
const int MAXN=111;
using namespace std;
stackS;
int edge[MAXN][MAXN];
int n,m;
void dfs(int x){
S.push(x);
for(int i=1;i<=n;i++){
if(edge[x][i]>0){
edge[i][x]=edge[x][i]=0;//删除此边
dfs(i);
break;
}
}
}
//Fleury算法的实现
void Fleury(int x){
S.push(x);
while(!S.empty()){
int b=0;
for(int i=1;i<=n;i++){
if(edge[S.top()][i]>0){
b=1;
break;
}
}
if(b==0){
printf("%d",S.top());
S.pop();
}else {
int y=S.top();
S.pop();
dfs(y);//如果有,就dfs
}
}
printf("\n");
}
int main(){
scanf("%d%d",&n,&m); //读入顶点数以及边数
memset(edge,0,sizeof(edge));
int x,y;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
edge[x][y]=edge[y][x]=1;
}
//如果存在奇数顶点,则从奇数顶点出发,否则从顶点0出发
int num=0,start=1;
for(int i=1;i<=n;i++){ //判断是否存在欧拉回路
int degree=0;
for(int j=1;j<=n;j++){
degree+=edge[i][j];
}
if(degree&1){
start=i,num++;
}
}
if(num==0||num==2){
Fleury(start);
}else
printf("No Euler Path\n");
return 0;
}