欧拉图浅析及模板

  • Post author:
  • Post category:其他


首先, 什么是欧拉回路。定义:

通过图(


无向图





有向图


)中所有边且每边仅通过一次通路称为欧拉通路,相应的回路称为欧拉回路。具有


欧拉回路


的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为


半欧拉图



要明确,有向图的欧拉回路和无向图的欧拉回路是不同的,其次,欧拉回路与欧拉通路也是不同的。

无向图:

欧拉回路:所有点的度都为偶数。度:即该点连接的路径,无向图中,不分出度与入度。

可以随便从一点出发,经过所有的边,再次回到这一点

欧拉通路:有两个点的度为奇数。此时可以从其中一个度为奇数点经过其他的点最终到达 另一个度为奇数的点

有向图:

入度:从一条边指向这一点,则这一点的入度+1

出度:有一条边从该点出发指向其他点,则这一点的出度+1

欧拉回路:所有点的入度等于该点的出度

欧拉通路:起点的入度等于起点的出度-1,终点的入度等于终点的出度+1,其他点的入 度都等于该点的出度

无向图存在欧拉回路的充要条件:

当且仅当该图所有顶点度数都为偶数且该图是连通图

有向图存在欧拉回路的充要条件:

当且仅当所有顶点的入度等于出度且该图是连通图

无向图的欧拉回路模板:

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

const int MX=1e5+5;
struct Edge{            //利用邻接表实现
    int v,nxt;
}E[MX*2];
int Head[MX],erear;
void edge_init(){
    erear=0;
    memset(Head,-1,sizeof(Head));
}
void edge_add(int u,int v){
    E[erear].v=v;
    E[erear].nxt=Head[u];
    Head[u]=erear++;
}

bool vis[MX];
int IN[MX],P[MX],sz;
void Fleury(int u){
    for(int i=Head[u];~i;i=Head[u]){
        int v=E[i].v;
        Head[u]=E[i].nxt;               //下一个点指向上一个点,即删去这条边
        if(vis[i|1]) continue;          //判断是否已经使用过
        vis[i|1]=1;
        Fleury(v);
    }
    P[++sz]=u;
}


int DU[MX];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    edge_init();
    memset(DU,0,sizeof(DU));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        edge_add(u,v);
        edge_add(v,u);
        DU[u]++;DU[v]++;
    }

    int cnt=0,rt;//a入度为奇数的个数
    for(int i=1;i<=n;i++){
        if(DU[i]%2==1){
            cnt++;rt=i;
        }
    }
    if(cnt!=2&&cnt!=0){
        printf("invalid\n");
        return 0;
    }
    if(cnt==0) rt=1;

    sz=0;
    Fleury(rt);
    for(int i=sz;i>=1;i--){
        printf("%d ",P[i]);
    }
    return 0;
}



版权声明:本文为Wyx_wx原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。