欧拉路径详解

时间:2019-08-19
本文章向大家介绍欧拉路径详解,主要包括欧拉路径详解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

什么是欧拉路径?欧拉路径就是一条能够不重不漏地经过图上的每一条边的路径,即小学奥数中的一笔画问题。而若这条路径的起点和终点相同,则将这条路径称为欧拉回路。

如何判断一个图是否有欧拉路径呢?显然,与一笔画问题相同,一个图有欧拉路径需要以下几个条件:

  • 首先,这是一个连通图
  • 若是无向图,则这个图的度数为奇数的点的个数必须是0或2;若是有向图,则要么所有点的入度和出度相等,要么有且只有两个点的入度分别比出度大1和少1

上面这两个条件很好证明。查找欧拉路径前,必须先保证该图满足以上两个条件,否则直接判误即可。

查找欧拉路径的算法有Fluery算法和Hierholzer算法。下面介绍一下Hierholzer算法。

算法流程:

  1. 对于无向图,判断度数为奇数的点的个数,若为0,则设任意一点为起点,若为2,则从这2个点中任取一个作为起点;对于有向图,判断入度和出度不同的点的个数,若为0,则设任意一点为起点,若为2,则设入度比出度小1的点为起点,另一点为终点。具体起点的选择要视题目要求而定。
  2. 从起点开始进行递归:对于当前节点x,扫描与x相连的所有边,当扫描到一条(x,y)时,删除该边,并递归y。扫描完所有边后,将x加入答案队列。
  3. 倒序输出答案队列。(因为这里是倒序输出,我们可以用栈来存储答案,当然用双端队列也可以)

解析:

从起点开始,每一次执行递归函数,相当于模拟一笔画的过程。递归的边界显然就是路径的终点,对于一个有欧拉路径的图,此时图上的所有边都已被删除,自然就不能继续递归。由于存储答案是在遍历以后进行的,答案存储也就是倒序的,因此要倒序输出答案。

代码:

#include<iostream>
#include<stack>
using namespace std;
const int N=500;
int n,tot,c=N,jp[N],cnt[N],edge[N][N];
char a,b;
stack<int> q;
void dfs(int now)
{
    for(int i=1;i<=N;i++)
        if(edge[now][i]==1)
        {
            edge[now][i]--,edge[i][now]--;
            dfs(i);
        }
    q.push(now);//加入答案队列
}//算法过程
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a>>b;
        c=min(c,a);
        c=min(c,b);
        edge[a][b]++,edge[b][a]++;
        cnt[a]++;
        cnt[b]++;//统计每个节点的度数
    }
    for(int i=1;i<=N;i++)
        if(cnt[i]%2==1)
            jp[tot++]=i;//找出度数为奇数的节点
    if(tot!=2 && tot)
    {
        cout<<"No Solution";
        return 0;
    }//若该图没有欧拉路径则判误
    int stat;
    if(tot)
        stat=min(jp[0],jp[1]);
    else
        stat=c;//找出起点
    dfs(stat);
    while(!q.empty())
    {
        char ct=q.top();
        cout<<ct;
        q.pop();
    }//倒序输出
    return 0;
}

在上面的代码中,找出的是起点字典序最小的欧拉路径,具体情况应视题意而定。


习题:


2019.4.16 于厦门外国语学校石狮分校

原文地址:https://www.cnblogs.com/TEoS/p/11376707.html