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;
    }
    
  • 相关阅读:
    github上传文件让别人下载--xdd
    C#Windows Forms 使MessageBox顶层显示--xdd
    2019.7.16.5.21留念
    Fortran流程控制与逻辑运算、循环--xdd
    Fortran输入输出与声明--xdd
    c#关于数据和方法在不同类中的引用-xdd
    C#Windows Forms (Demo.SYS)--xdd
    github下载历史版本--xdd
    Matlab查看本机IP地址---xdd
    Matlab生成Word--xdd
  • 原文地址:https://www.cnblogs.com/baccano-acmer/p/9925197.html
Copyright © 2011-2022 走看看