zoukankan      html  css  js  c++  java
  • 欧拉回路

    一、引言

    欧拉回路问题是图论中最古老的问题,诞生于18世纪欧洲的科尼斯堡问题

    二、定义

    (G=(V,E))是一个图。

    欧拉回路:图G中经过每条边一次并且仅一次的回路。

    欧拉路径:图G中经过每条边一次并且仅一次的路径。

    欧拉图:存在欧拉回路的图。

    半欧拉图:存在欧拉路径但不存在欧拉回路的图。

    三、性质与定理

    假设下面讨论的图G不存在孤立点,否则,先将孤立点从图中删除。
    

    对于无向图:

    定理1:无向图G为欧拉图,当且仅当G为连通图且所有定点的度为偶数。

    推论1:无向图G为半欧拉图,当且仅当G为连通图且除了两个顶点的度为奇数之外,其它所有顶点的度为偶数。

    对于有向图:

    定理2:有向图G为欧拉图,当且仅当G的基图连通,且所有顶点的入度等于出度。

    推论2:有向图G为半欧拉图,当且仅当G的基图连通,且存在顶点u的入度比出度大1,v的入度比出度小1,其它所有顶点的入度等于出度。

    基图:忽略有向图所有边的方向,得到的无向图成为该有向图的基图。
    

    四、求欧拉回路

    两种:Hierholzer(套圈)算法和Fluery算法,前者编程简单,时间复杂度更优,后者应用性更广泛,这里不深入分析。

    Hierholzer算法:

    #include<iostream>
    #include<cstdio>
    #include<set>
    using namespace std;
    const int N=1025;
    multiset<int> h[N];
    int degree[N], road[N], k;
    
    void dfs(int x)
    {
        for(multiset<int>::iterator py=h[x].begin(); py!=h[x].end(); py=h[x].begin()){
            int y=*py;													 
            h[x].erase(py);												//删边x->y 
            h[y].erase(h[y].find(x));									//删边x->y
            dfs(y);														//从y递归 
        }
        road[k++]=x;													//往队列里插入答案 
    }
    
    int main(){
        int F, s=0, t=0;												//s起点,t终点 
        scanf("%d", &F);
        for(int i=1, a, b; i<=F; i++)	scanf("%d%d", &a, &b), degree[a]++, degree[b]++, h[a].insert(b), h[b].insert(a);
        for(int i=1; i<=1024; i++)										//注意模板题中栅栏结点的编号范围不是1~F 
        {
            if(degree[i]%2){											//发现奇点 
                if(!s)			s=i;
                else if(!t)		t=i;
                else 			return 0;								//发现奇点超过2个,无欧拉路径 
            }
    	}
    	if(s && !t)	return 0;											//只有1个奇点,无欧拉路径
    	if(!s)	s=1;													//没有奇点,有欧拉回路,指定1为起点 
        dfs(s);
        for(k=k-1; k>=0; k--)	printf("%d
    ", road[k]);				//倒序输出答案,也可以不用road数组,使用一个stack 
        return 0;
    }
    
    
    效率分析:共插入了2E条边,dfs共遍历2E条边。使用multiset可便于快速查找最小值,查找,删除边的复杂度为lgn,故程序时间复杂度为O(Elgn)。
    

  • 相关阅读:
    nginx的安装及简单负载均衡配置
    memcached 的配置及 spymemcached 客户端简单使用
    我的github地址
    学习3ds max插件开发过程中的一些小结
    编译opengl编程指南第八版示例代码通过
    lua执行字节码的过程介绍
    lua解析赋值类型代码的过程
    lua解析脚本过程中的关键数据结构介绍
    lua解释执行脚本流程
    lua中的string类型
  • 原文地址:https://www.cnblogs.com/lfyzoi/p/10789663.html
Copyright © 2011-2022 走看看