[Lemon-commits] [lemon_svn] alpar: r2367 - hugo/trunk/lemon

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:52:06 CET 2006


Author: alpar
Date: Mon Nov 21 10:08:16 2005
New Revision: 2367

Modified:
   hugo/trunk/lemon/euler.h

Log:
UndirEulerIt added

Modified: hugo/trunk/lemon/euler.h
==============================================================================
--- hugo/trunk/lemon/euler.h	(original)
+++ hugo/trunk/lemon/euler.h	Mon Nov 21 10:08:16 2005
@@ -1,5 +1,5 @@
 /* -*- C++ -*-
- * lemon/topology.h - Part of LEMON, a generic C++ optimization library
+ * lemon/euler.h - Part of LEMON, a generic C++ optimization library
  *
  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
  * (Egervary Research Group on Combinatorial Optimization, EGRES).
@@ -14,6 +14,7 @@
  *
  */
 #include<lemon/invalid.h>
+#include<lemon/topology.h>
 #include <list>
 
 /// \ingroup topology
@@ -26,7 +27,7 @@
 
 namespace lemon {
 
-  ///Euler iterator in directed graphs.
+  ///Euler iterator for directed graphs.
 
   /// \ingroup topology
   ///This iterator converts to the \c Edge type of the graph and using
@@ -111,31 +112,133 @@
     }
   };
 
+  ///Euler iterator for undirected graphs.
+
+  /// \ingroup topology
+  ///This iterator converts to the \c Edge type of the graph and using
+  ///operator ++ it provides an Euler tour of the graph (if there exists).
+  ///
+  ///For example
+  ///if the given graph if Euler (i.e it has only one nontrivial component
+  ///and the degree of each node is even),
+  ///the following code will print the edge IDs according to an
+  ///Euler tour of \c g.
+  ///\code
+  ///  for(UndirEulerIt<UndirListGraph> e(g),e!=INVALID;++e) {
+  ///    std::cout << g.id(UndirEdge(e)) << std::eol;
+  ///  }
+  ///\endcode
+  ///Although the iterator provides an Euler tour of an undirected graph,
+  ///in order to indicate the direction of the tour, UndirEulerIt
+  ///returns directed edges (that convert to the undirected ones, of course).
+  ///
+  ///If \c g is not Euler then the resulted tour will not be full or closed.
+  ///\todo Test required
+  template<class Graph>
+  class UndirEulerIt
+  {
+    typedef typename Graph::Node Node;
+    typedef typename Graph::NodeIt NodeIt;
+    typedef typename Graph::Edge Edge;
+    typedef typename Graph::EdgeIt EdgeIt;
+    typedef typename Graph::OutEdgeIt OutEdgeIt;
+    typedef typename Graph::InEdgeIt InEdgeIt;
+    
+    const Graph &g;
+    typename Graph::NodeMap<OutEdgeIt> nedge;
+    typename Graph::UndirEdgeMap<bool> visited;
+    std::list<Edge> euler;
+
+  public:
+    
+    ///Constructor
+
+    ///\param _g An undirected graph.
+    ///\param start The starting point of the tour. If it is not given
+    ///       the tour will start from the first node.
+    UndirEulerIt(const Graph &_g,typename Graph::Node start=INVALID)
+      : g(_g), nedge(g), visited(g,false)
+    {
+      if(start==INVALID) start=NodeIt(g);
+      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n);
+      while(nedge[start]!=INVALID) {
+	euler.push_back(nedge[start]);
+	Node next=g.target(nedge[start]);
+	++nedge[start];
+	start=next;	while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
+      }
+    }
+    
+    ///Edge Conversion
+    operator Edge() { return euler.empty()?INVALID:euler.front(); }
+    bool operator==(Invalid) { return euler.empty(); }
+    bool operator!=(Invalid) { return !euler.empty(); }
+    
+    ///Next edge of the tour
+    UndirEulerIt &operator++() {
+      Node s=g.target(euler.front());
+      euler.pop_front();
+      typename std::list<Edge>::iterator next=euler.begin();
+
+      while(nedge[s]!=INVALID) {
+	while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
+	if(nedge[s]==INVALID) break;
+	else {
+	  euler.insert(next,nedge[s]);
+	  Node n=g.target(nedge[s]);
+	  ++nedge[s];
+	  s=n;
+	}
+      }
+      return *this;
+    }
+    
+    ///Postfix incrementation
+    
+    ///\warning This incrementation
+    ///returns an \c Edge, not an \ref UndirEulerIt, as one may
+    ///expect.
+    Edge operator++(int) 
+    {
+      Edge e=*this;
+      ++(*this);
+      return e;
+    }
+  };
+
+
   ///Checks if the graph is Euler
 
-  /// \ingroup gutils
+  /// \ingroup topology
   ///Checks if the graph is Euler. It works for both directed and
   ///undirected graphs.
+  ///\note By definition, a directed graph is called \e Euler if
+  ///and only if connected and the number of it is incoming and outgoing edges
+  ///are the same for each node.
+  ///Similarly, an undirected graph is called \e Euler if
+  ///and only if it is connected and the number of incident edges is even
+  ///for each node. <em>Therefore, there are graphs which are not Euler, but
+  ///still have an Euler tour</em>.
   ///\todo Test required
   template<class Graph>
 #ifdef DOXYGEN
   bool
 #else
   typename enable_if<typename Graph::UndirTag,bool>::type
-#endif
   euler(const Graph &g) 
   {
     for(typename Graph::NodeIt n(g);n!=INVALID;++n)
       if(countIncEdges(g,n)%2) return false;
-    return true;
+    return connected(g);
   }
   template<class Graph>
   typename disable_if<typename Graph::UndirTag,bool>::type
+#endif
   euler(const Graph &g) 
   {
     for(typename Graph::NodeIt n(g);n!=INVALID;++n)
       if(countInEdges(g,n)!=countOutEdges(g,n)) return false;
-    return true;
+    return connected(g);
   }
   
 }



More information about the Lemon-commits mailing list