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

    什么是欧拉回路?

    一句话概括就是在一个双向图中,如果从一个节点开始经历整个图的所有边有且仅有一次,然后回到了起点,这个就是欧拉回路。如果图存在欧拉回路,那么这条从起点出发回到起点的路径称为欧拉路径。

    例如

    这个不是欧拉回路

    这个是欧拉回路

    怎么样才会生成欧拉回路?

    只有三种情况

    ①节点的度数全部为偶数。

    ②存在一个奇数节点。

    ③存在两个奇数节点

    ④如果存在三个或三个以上的奇数节点,那么肯定无法构成欧拉回路

    欧拉回路的起点如何选择?

    ①对于全部偶数度数的图来说,起始节点是任意的。

    ②如果存在奇数点,那么一定从奇数点开始。

    ③如果存在两个奇数点,那么一定从一个奇数点开始一个奇数点结束。

    如何实现欧拉回路的算法?

    Hierholzer算法

    wiki

    wiki原文

    Hierholzer's 1873 paper provides a different method for finding Euler cycles that is more efficient than Fleury's algorithm:

    ·Choose any starting vertex v, and follow a trail of edges from that vertex until returning to v. It is not possible to get stuck at any vertex other than v, because the even degree of all vertices ensures that, when the trail enters another vertex w there must be an unused edge leaving w. The tour formed in this way is a closed tour, but may not cover all the vertices and edges of the initial graph.

    ·As long as there exists a vertex u that belongs to the current tour but that has adjacent edges not part of the tour, start another trail from u, following unused edges until returning to u, and join the tour formed in this way to the previous tour.

    By using a data structure such as a doubly linked list to maintain the set of unused edges incident to each vertex, to maintain the list of vertices on the current tour that have unused edges, and to maintain the tour itself, the individual operations of the algorithm (finding unused edges exiting each vertex, finding a new starting vertex for a tour, and connecting two tours that share a vertex) may be performed in constant time each, so the overall algorithm takes linear time, {displaystyle O(|E|)} O(|E|).[8]

    代码模板

    #include <bits/stdc++.h>
    using namespace std;
    //二位数组G用来存图,du是保存每个节点的度数,jl是保存欧拉路径的数组
    int G[1500][1500],du[1500],jl[1500];
    //mi是最小值,因为节点不一定是从1开始,maxn保存最大的节点,start是开始的节点,p是数组计数器
    int mi=INT_MAX,maxn,start=1,p;
    void dfs(int num)//核心算法
    {
      for(int i=mi;i<=maxn;i++)//对每一个节点进行枚举,如果存在连通的情况,那么边数--,继续搜索下一个连通的节点
      if(G[num][i])
      {
        G[num][i]--;
        G[i][num]--;
        dfs(i);
      }
      jl[p++]=num;//路径存入数组
    }
    int main()
    {
      int m;
      cin>>m;
      while(m--)
      {
        int t1,t2;
        cin>>t1>>t2;
        G[t1][t2]++;
        G[t2][t1]++;
        du[t1]++;du[t2]++;
        maxn=max(max(maxn,t1),max(maxn,t2));//找最大值和最小值
        mi=min(min(mi,t1),min(mi,t2));
      }
      for(int i=mi;i<=maxn;i++)
      if(du[i]%2)//寻找最小的奇点
      {
        start=i;
        break;
      }
      dfs(start);
      for(int i=p-1;i>=0;i--)//根据递归返回的性质,应该倒叙输出
      cout<<jl[i]<<endl;
    }
    
  • 相关阅读:
    如何手动封装 $ on off emit?
    Vue 实例身上的一些方法(二)
    Vue 实例身上的一些方法(一)
    Vue属性过滤
    Vue属性监听
    Vue实现简单的商品增减功能
    Vue 计算属性
    使用Vue实现一个简单地自定义拖拽功能
    数组的深拷贝与浅拷贝
    如何让html引用公共布局(多个html文件公用一个header.html和footer.html)
  • 原文地址:https://www.cnblogs.com/baccano-acmer/p/9925197.html
Copyright © 2011-2022 走看看