fleury算法输出欧拉回路

本文介绍了欧拉路径和欧拉回路的概念,并详细阐述了无向图与有向图成为欧拉图和半欧拉图的条件。此外,还提供了Fleury算法的具体步骤,用于求解无向图中的欧拉回路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、定义:
欧拉通路(回路):通过图(无向图或有向图)中所有一次且仅一次行遍图中所有顶点的
    通路(回路)称为欧拉通路(回路)。
欧拉图与半欧拉图:具有欧拉回路的图称为欧拉图,具有欧拉通路而无欧拉回路的
    图称为半欧拉图。
:设无向图G=<V,E>,若存在边集E的一个非空子集E1,使得p(G-E1)>p(G),而对
    于E1的任意真子集E2,均有p(G-E2)=p(G),则称E1是G的边割集,或简称割集;
    若E1是单元集,即E1={e},则称e为割边或。[p(G)表示图G的连通分支数.]
 
2、定理:
<无向图>
定理1:无向图G是欧拉图当且仅当G是连通图,且G中没有奇度顶点。
定理2:无向图G是半欧拉图当且仅当G是连通图,且G中恰有两个奇度顶点。
 
<有向图>
定理1:有向图D是欧拉图当且仅当D是强连通的且每个顶点的入度都等于出度。
定理2:有向图D是半欧拉图当且仅当D是单向连通的,且D中恰有两个奇度顶点,其
       中一个入度比出度大1,另一个的出度比入度大1,而其余顶点的入度都等于
       出度。
 
3、求欧拉回路的Fleury算法:
   设G为欧拉图,一般说来G中存在若干条欧拉回路,下面是求欧拉回路的Fleury算法:
Fleury算法:
(1)任取v0∈V(G),令P0=v0;
(2)设Pi=v0e1v1e2...eivi已经行遍,按下面方法来从E(G)-{e1,e2,...,ei}中选
     取ei+1:
    (a)ei+1与vi想关联;
    (b)除非无别的边可供行遍,否则ei+1不应该为Gi=G-{e1,e2,...,ei}中的桥.
(3)当(2)不能再进行时,算法停止。

可以证明,当算法停止时所得简单回路Pm=v0e1v1e2...emvm(vm=v0)为G中的一条欧拉回路




#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
stack<int>que;
int a[1000][1000];
int n,m;
void dfs(int x)
{
    int i;
    que.push(x);
    for(i=1;i<=n;i++)
    {
        if(a[x][i]>0)
        {
            a[x][i]=0;
            a[i][x]=0;
            dfs(i);
            break;
        }
    }
}
void fleury(int x)
{
    int i,j;
    int b;
    que.push(x);
    while(!que.empty())
    {
        b=0;
        for(i=1;i<=n;i++)
        {
            if(a[que.top()][i]>0)
            {
                b=1;
                break;
            }
        }
        if(b==0)
        {
            printf("%d ",que.top());
            que.pop();
        }
        else
        {
            int y=que.top();
            que.pop();
            dfs(y);
        }
    }
    printf("\n");
    return ;
}
int main()
{
    int i,j,p,q;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        memset(a,0,sizeof(a));
            for(j=1;j<=m;j++)
            {
                scanf("%d %d",&p,&q);
                a[p][q]=a[q][p]=1;
            }
        int num=0;
        int start=1;
        int degree=0;
        for(i=1;i<=n;i++)
        {
            degree=0;
            for(j=1;j<=n;j++)
            {
                degree+=a[i][j];
            }
            if(degree%2==1)
            {
                start=i;
                num++;
            }
        }
        if(num==0||num==2)
        {
            fleury(start);
        }
        else
        {
            printf("NO Eular path\n");
        }
        while(!que.empty())
        {
            que.pop();
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值