1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
22 #include<lemon/core.h>
23 #include<lemon/adaptors.h>
24 #include<lemon/connectivity.h>
27 /// \ingroup graph_properties
31 ///This file provides an Euler tour iterator and ways to check
32 ///if a digraph is euler.
37 ///Euler iterator for digraphs.
39 /// \ingroup graph_properties
40 ///This iterator converts to the \c Arc type of the digraph and using
41 ///operator ++, it provides an Euler tour of a \e directed
42 ///graph (if there exists).
45 ///if the given digraph is Euler (i.e it has only one nontrivial component
46 ///and the in-degree is equal to the out-degree for all nodes),
47 ///the following code will put the arcs of \c g
48 ///to the vector \c et according to an
49 ///Euler tour of \c g.
51 /// std::vector<ListDigraph::Arc> et;
52 /// for(DiEulerIt<ListDigraph> e(g),e!=INVALID;++e)
55 ///If \c g is not Euler then the resulted tour will not be full or closed.
60 typedef typename GR::Node Node;
61 typedef typename GR::NodeIt NodeIt;
62 typedef typename GR::Arc Arc;
63 typedef typename GR::ArcIt ArcIt;
64 typedef typename GR::OutArcIt OutArcIt;
65 typedef typename GR::InArcIt InArcIt;
68 typename GR::template NodeMap<OutArcIt> nedge;
75 ///\param gr A digraph.
76 ///\param start The starting point of the tour. If it is not given
77 /// the tour will start from the first node.
78 DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
81 if(start==INVALID) start=NodeIt(g);
82 for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
83 while(nedge[start]!=INVALID) {
84 euler.push_back(nedge[start]);
85 Node next=g.target(nedge[start]);
92 operator Arc() { return euler.empty()?INVALID:euler.front(); }
93 bool operator==(Invalid) { return euler.empty(); }
94 bool operator!=(Invalid) { return !euler.empty(); }
96 ///Next arc of the tour
97 DiEulerIt &operator++() {
98 Node s=g.target(euler.front());
100 //This produces a warning.Strange.
101 //std::list<Arc>::iterator next=euler.begin();
102 typename std::list<Arc>::iterator next=euler.begin();
103 while(nedge[s]!=INVALID) {
104 euler.insert(next,nedge[s]);
105 Node n=g.target(nedge[s]);
111 ///Postfix incrementation
113 ///\warning This incrementation
114 ///returns an \c Arc, not an \ref DiEulerIt, as one may
124 ///Euler iterator for graphs.
126 /// \ingroup graph_properties
127 ///This iterator converts to the \c Arc (or \c Edge)
128 ///type of the digraph and using
129 ///operator ++, it provides an Euler tour of an undirected
130 ///digraph (if there exists).
133 ///if the given digraph if Euler (i.e it has only one nontrivial component
134 ///and the degree of each node is even),
135 ///the following code will print the arc IDs according to an
136 ///Euler tour of \c g.
138 /// for(EulerIt<ListGraph> e(g),e!=INVALID;++e) {
139 /// std::cout << g.id(Edge(e)) << std::eol;
142 ///Although the iterator provides an Euler tour of an graph,
143 ///it still returns Arcs in order to indicate the direction of the tour.
144 ///(But Arc will convert to Edges, of course).
146 ///If \c g is not Euler then the resulted tour will not be full or closed.
148 template<typename GR>
151 typedef typename GR::Node Node;
152 typedef typename GR::NodeIt NodeIt;
153 typedef typename GR::Arc Arc;
154 typedef typename GR::Edge Edge;
155 typedef typename GR::ArcIt ArcIt;
156 typedef typename GR::OutArcIt OutArcIt;
157 typedef typename GR::InArcIt InArcIt;
160 typename GR::template NodeMap<OutArcIt> nedge;
161 typename GR::template EdgeMap<bool> visited;
162 std::list<Arc> euler;
168 ///\param gr An graph.
169 ///\param start The starting point of the tour. If it is not given
170 /// the tour will start from the first node.
171 EulerIt(const GR &gr, typename GR::Node start = INVALID)
172 : g(gr), nedge(g), visited(g, false)
174 if(start==INVALID) start=NodeIt(g);
175 for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
176 while(nedge[start]!=INVALID) {
177 euler.push_back(nedge[start]);
178 visited[nedge[start]]=true;
179 Node next=g.target(nedge[start]);
182 while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
187 operator Arc() const { return euler.empty()?INVALID:euler.front(); }
189 operator Edge() const { return euler.empty()?INVALID:euler.front(); }
191 bool operator==(Invalid) const { return euler.empty(); }
193 bool operator!=(Invalid) const { return !euler.empty(); }
195 ///Next arc of the tour
196 EulerIt &operator++() {
197 Node s=g.target(euler.front());
199 typename std::list<Arc>::iterator next=euler.begin();
201 while(nedge[s]!=INVALID) {
202 while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
203 if(nedge[s]==INVALID) break;
205 euler.insert(next,nedge[s]);
206 visited[nedge[s]]=true;
207 Node n=g.target(nedge[s]);
215 ///Postfix incrementation
217 ///\warning This incrementation
218 ///returns an \c Arc, not an \ref EulerIt, as one may
229 ///Checks if the graph is Eulerian
231 /// \ingroup graph_properties
232 ///Checks if the graph is Eulerian. It works for both directed and undirected
234 ///\note By definition, a digraph is called \e Eulerian if
235 ///and only if it is connected and the number of its incoming and outgoing
236 ///arcs are the same for each node.
237 ///Similarly, an undirected graph is called \e Eulerian if
238 ///and only if it is connected and the number of incident arcs is even
239 ///for each node. <em>Therefore, there are digraphs which are not Eulerian,
240 ///but still have an Euler tour</em>.
241 template<typename GR>
245 typename enable_if<UndirectedTagIndicator<GR>,bool>::type
246 eulerian(const GR &g)
248 for(typename GR::NodeIt n(g);n!=INVALID;++n)
249 if(countIncEdges(g,n)%2) return false;
253 typename disable_if<UndirectedTagIndicator<GR>,bool>::type
255 eulerian(const GR &g)
257 for(typename GR::NodeIt n(g);n!=INVALID;++n)
258 if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
259 return connected(Undirector<const GR>(g));