[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