1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2010
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
29 /// \brief Euler tour iterators and a function for checking the \e Eulerian
32 ///This file provides Euler tour iterators and a function to check
33 ///if a (di)graph is \e Eulerian.
37 ///Euler tour iterator for digraphs.
39 /// \ingroup graph_properties
40 ///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
41 ///graph (if there exists) and it converts to the \c Arc type of the digraph.
43 ///For example, if the given digraph has an Euler tour (i.e it has only one
44 ///non-trivial component and the in-degree is equal to the out-degree
45 ///for all nodes), then the following code will put the arcs of \c g
46 ///to the vector \c et according to an Euler tour of \c g.
48 /// std::vector<ListDigraph::Arc> et;
49 /// for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
52 ///If \c g has no Euler tour, then the resulted walk will not be closed
53 ///or not contain all arcs.
58 typedef typename GR::Node Node;
59 typedef typename GR::NodeIt NodeIt;
60 typedef typename GR::Arc Arc;
61 typedef typename GR::ArcIt ArcIt;
62 typedef typename GR::OutArcIt OutArcIt;
63 typedef typename GR::InArcIt InArcIt;
66 typename GR::template NodeMap<OutArcIt> narc;
74 ///\param gr A digraph.
75 ///\param start The starting point of the tour. If it is not given,
76 ///the tour will start from the first node that has an outgoing arc.
77 DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
82 while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
86 for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
87 while (narc[start]!=INVALID) {
88 euler.push_back(narc[start]);
89 Node next=g.target(narc[start]);
97 operator Arc() { return euler.empty()?INVALID:euler.front(); }
98 ///Compare with \c INVALID
99 bool operator==(Invalid) { return euler.empty(); }
100 ///Compare with \c INVALID
101 bool operator!=(Invalid) { return !euler.empty(); }
103 ///Next arc of the tour
105 ///Next arc of the tour
107 DiEulerIt &operator++() {
108 Node s=g.target(euler.front());
110 typename std::list<Arc>::iterator next=euler.begin();
111 while(narc[s]!=INVALID) {
112 euler.insert(next,narc[s]);
113 Node n=g.target(narc[s]);
119 ///Postfix incrementation
121 /// Postfix incrementation.
123 ///\warning This incrementation
124 ///returns an \c Arc, not a \ref DiEulerIt, as one may
134 ///Euler tour iterator for graphs.
136 /// \ingroup graph_properties
137 ///This iterator provides an Euler tour (Eulerian circuit) of an
138 ///\e undirected graph (if there exists) and it converts to the \c Arc
139 ///and \c Edge types of the graph.
141 ///For example, if the given graph has an Euler tour (i.e it has only one
142 ///non-trivial component and the degree of each node is even),
143 ///the following code will print the arc IDs according to an
144 ///Euler tour of \c g.
146 /// for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
147 /// std::cout << g.id(Edge(e)) << std::eol;
150 ///Although this iterator is for undirected graphs, it still returns
151 ///arcs in order to indicate the direction of the tour.
152 ///(But arcs convert to edges, of course.)
154 ///If \c g has no Euler tour, then the resulted walk will not be closed
155 ///or not contain all edges.
156 template<typename GR>
159 typedef typename GR::Node Node;
160 typedef typename GR::NodeIt NodeIt;
161 typedef typename GR::Arc Arc;
162 typedef typename GR::Edge Edge;
163 typedef typename GR::ArcIt ArcIt;
164 typedef typename GR::OutArcIt OutArcIt;
165 typedef typename GR::InArcIt InArcIt;
168 typename GR::template NodeMap<OutArcIt> narc;
169 typename GR::template EdgeMap<bool> visited;
170 std::list<Arc> euler;
177 ///\param gr A graph.
178 ///\param start The starting point of the tour. If it is not given,
179 ///the tour will start from the first node that has an incident edge.
180 EulerIt(const GR &gr, typename GR::Node start = INVALID)
181 : g(gr), narc(g), visited(g, false)
183 if (start==INVALID) {
185 while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
188 if (start!=INVALID) {
189 for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
190 while(narc[start]!=INVALID) {
191 euler.push_back(narc[start]);
192 visited[narc[start]]=true;
193 Node next=g.target(narc[start]);
196 while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
202 operator Arc() const { return euler.empty()?INVALID:euler.front(); }
204 operator Edge() const { return euler.empty()?INVALID:euler.front(); }
205 ///Compare with \c INVALID
206 bool operator==(Invalid) const { return euler.empty(); }
207 ///Compare with \c INVALID
208 bool operator!=(Invalid) const { return !euler.empty(); }
210 ///Next arc of the tour
212 ///Next arc of the tour
214 EulerIt &operator++() {
215 Node s=g.target(euler.front());
217 typename std::list<Arc>::iterator next=euler.begin();
218 while(narc[s]!=INVALID) {
219 while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
220 if(narc[s]==INVALID) break;
222 euler.insert(next,narc[s]);
223 visited[narc[s]]=true;
224 Node n=g.target(narc[s]);
232 ///Postfix incrementation
234 /// Postfix incrementation.
236 ///\warning This incrementation returns an \c Arc (which converts to
237 ///an \c Edge), not an \ref EulerIt, as one may expect.
247 ///Check if the given graph is Eulerian
249 /// \ingroup graph_properties
250 ///This function checks if the given graph is Eulerian.
251 ///It works for both directed and undirected graphs.
253 ///By definition, a digraph is called \e Eulerian if
254 ///and only if it is connected and the number of incoming and outgoing
255 ///arcs are the same for each node.
256 ///Similarly, an undirected graph is called \e Eulerian if
257 ///and only if it is connected and the number of incident edges is even
260 ///\note There are (di)graphs that are not Eulerian, but still have an
261 /// Euler tour, since they may contain isolated nodes.
263 ///\sa DiEulerIt, EulerIt
264 template<typename GR>
268 typename enable_if<UndirectedTagIndicator<GR>,bool>::type
269 eulerian(const GR &g)
271 for(typename GR::NodeIt n(g);n!=INVALID;++n)
272 if(countIncEdges(g,n)%2) return false;
276 typename disable_if<UndirectedTagIndicator<GR>,bool>::type
278 eulerian(const GR &g)
280 for(typename GR::NodeIt n(g);n!=INVALID;++n)
281 if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
282 return connected(undirector(g));