欧拉回路

欧拉回路与欧拉道路

图G的一个回路,若它恰通过G中每条边一次,则称该回路为欧拉(Euler)回路。
如果一个图只是形成一个连通所有节点的链,且每一点只走一次,则成为欧拉道路。
具有欧拉回路或欧拉道路的图称为欧拉图(简称E图)。
有向图的欧拉回路
一个有向图存在欧拉回路的前提条件是这个图是个连通图,其次要求其每个点的入度等于出度,或者其中有一个点的出度比入度大1,另一个点的入度比出度大一这样就存在一条欧拉回路。
如果其每个点的入度等于出度则从任意一点出发,可以走出一条欧拉回路,如果是第二种情况,则必须从出度大于入度 1 的点出发到入度大于出度 1 的点结束,走出一条欧拉道路。
无向图的欧拉回路
跟有向图一样,首先必须连通,其次如果最多只有两个奇点。则满足欧拉回路或欧拉道路,有奇点就从任意一个奇点出发找科形成一条欧拉道路,否则从任意一点出发都能找出欧拉回路。(注意:百度百科上是错的)

如果只是判断一个图是否能够形成欧拉回路的话,就用上面的思路:
首先根据出度跟入度的关系,判断是否满足要求
然后用判断图的连通性可以用并查集或者Dfs如果要求路径的话可以用Dfs

要是需要求出欧拉路径,就用下面这个函数。
下面这个程序,是通过遍历一个图来求其欧拉回路或欧拉道路的。如果需要打印欧拉道路,在主程序中调用,参数必须是道路的起点,另外说明的是,这样打印出来是逆序的,因此在使用的时候,应该用栈压入栈中,还有就是其对无向图和有向图遍历都有用。其实这个算法跟最小生成树prim里面每次求连接上一边最小权值的边算法一样,这个只是那个算法的一个简化。可根据那个进行理解。

#include<iostream>  
#include<stack>  
const int MAXN=111;  
using namespace std;  

stack<int>S;  
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;  
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值