欧拉图详解

欧拉图

欧拉图
定义:
  • 欧拉回路:若存在一条从起点S出发的路径,每条边恰好只走一次,最终回到起点S的路径被称为欧拉路径。

  • 欧拉通路:若存在一条从起点S出发的路径,经过每条边一次,但是不要求回到起点S的路径被称作欧拉通路。

每条路都走,而且只走一次,并且能回到起点的,是欧拉图,也称欧拉回路。
每条路都走,而且只走一次,不能回到起点的,是半欧拉图,也称欧拉路径。

判定方法:

前提:图都是连通图

无向图:

当一个无向图是欧拉图时,它的所有顶点的度数都是偶数,即它没有奇度顶点。

当一个无向图是半欧拉图时,它有且只有2个奇度顶点

有向图:

当一个有向图是欧拉图时,它的所有顶点都处于一个强连通分量中,并且出度=入度

强连通分量:强连通分量指强连通分量中的任意两个点都有路径互相到达。

当一个有向图是半欧拉图时,它的所有顶点都处于一个强连通分量中,且:

最多只有一个顶点的出度与入度差为 1 。
最多只有一个顶点的入度与出度差为 1 。
所有其他顶点的入度和出度相同。
Hierholzier 算法(蓝书P409)时间复杂度O(n*m)

(1)判断奇度数点,奇度数点若为 0 0 0则任意指定起点,奇度数点为 2 2 2则从指定其中任意一个。

(2)对于当前节点 x x x,扫描与 x x x相连的所有边,当扫描到一条边 ( x , y ) (x,y) (x,y)时,删除该边以及边 ( y , x ) (y,x) (y,x),并递归 y y y。扫描完所有边后,将 x x x加入答案队列。

(3)倒序输出答案队列。

#include<iostream>
#include<cstdio>
using namespace std;

const int maxn=1e5+5;
const int maxm=1e5+5;
struct edge
{
    int to,nxt;
}Edge[maxm<<1];

int head[maxn],Stack[maxm<<1],ans[maxm<<1];
bool vis[maxn<<1];
int n,m,tot=1,top,num;//tot一定要从1开始

void addedge(int x,int y)
{
    Edge[++tot].to=y,Edge[tot].nxt=head[x],head[x]=tot;
}

void euler()
{
    top=0;
    Stack[++top]=1;//用数组模拟栈
    int x,i;
    while(top>0)//模拟dfs
    {
        x=Stack[top],i=head[x];
        while(i&&vis[i])
            i=Edge[i].nxt;//找一条没有走过的
        if(i)
        {
            Stack[++top]=Edge[i].to;
            vis[i]=vis[i^1]=1;//有向图则只标记一条边
            head[x]=Edge[i].nxt;//删去已经走过的边,仔细体会删去的含义
        }
        else//x已经访问完毕 回溯过程
        {
            --top;
            ans[++num]=x;
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y),addedge(y,x);
    }
    euler();
    for(int i=num;i>=1;i--)//倒序输出
        printf("%d\n",ans[i]);
    return 0;
}

如果我们每次都贪心取编号最小的顶点,那么得到的欧拉迹是所有欧拉迹中编号字典序最小的(提示:可以用multiset)

例题:无序字母对

无序字母对

解法:将字母对的关系看成点与点的关系,中间用一条边相连,字符串即它们的欧拉回路。

欧拉图题单

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值