欧拉图与欧拉路

来源:互联网 发布:nginx rtmp 直播配置 编辑:程序博客网 时间:2024/03/28 22:55
定义:给定无孤立结点图G,若存在一条路,经过图中海边一次且仅一次,该条路称为欧拉路;若存在一条回路,经过图中海边一次且仅一次,该回路称为欧拉回路。具有欧拉回路的图称作欧拉图。


定理:无向图G具有一条欧拉路,当且仅当G是连通的,且有零个或两个奇数度结点。欧拉路和欧拉回路的概念,很易推广到有向图中去。


有向欧拉图


定义:给定有向图G,通过图中每边一次且仅一次的一条单向路(回路),称作单向欧拉路(回路)。


定理:有向图G具有一条单向欧拉回路,当且仅当是连通的,且每个结点入度等于出度。一个有向图G具有单向欧拉路,当且仅当它是连通的,而且除两个结点外,每个结点的入度等于出度,但这两个结点中,一个结点的入度比出度大1,另一个结点的入度比出度小1。


找欧拉路(或回路)可以用Euler算法,如下:
(1)寻找从i出发的环p1p2…px(p1=px=i)。
(2)标记顶的p1->x为待查的状态。
(3)对所有处在待查状态的节点pj递归调用过程Euler(pj)


将Euler(pj)找到的环q1q2…qx插入到环p1p2…px中,得到回路p1p2…pjq1…qypj+1…px。时间复杂度为O(m)。


void Euler(int t){   int i;   for(i=edge[t].next;i!=-1;i=edge[i].next)   if(edge[i].t==-1)   {       edge[i].t=1;       Eluer(edge[i].v);       pop[top++]=edge[i].index;   }}



输出时只要逆序输出pop即可,而且当边是按字母序建边时,输出的也是按字母序的答案。


纯dfs算法实现Euler()正确性的证明:


假设节点s为起点,则深搜到不能搜的时候那个节点就是s。为什么呢,只要将这点想通,基本就没什么问题了。我们知道如果一个节点入度减1,那么它的出度必然要减1,在以s为起点的路径中,se1v1e2v2....eivi,如果vi节点不是s节点且为深搜的最后节点,也就是说vi没有了出度,然而我们知道对于v1...v(i-1)节点入度一但减少,出度也就减少了,然而对于s起点来说只要出度减少却没有入度减少,vi的入度减少却没有了出度,所以证明vi节点不可能会成为不是s节点且为深搜的最后节点,即除非他还不是深搜的最后节点,到这里我们基本就可以确定了,vi要满足深搜最后节点必然为vi==s,这样的话vi的入度减少了,出度也减少了(因为s出度减少了),s的出度减少了,入度也减少了(因为vi的入度减少了)所以可以证明以s为起点的深搜最后节点也为s。


然后就是返回了,当沿着路径返回的途中如果vi节点还有出度的话,那么就以vi为起点开始深搜,根据上面的证明,我们可以知道最后的深搜节点肯定为vi起点了。


将回路se1v1e2v2.....eivi(ei1vi1ei2vi2...eiivi)e(i+1).....ejs,括号里面的就是返回途中发生的又一次回路咯,把它嵌入到里面自然大的回路也满足要求了。


欧拉路时同理。