Location: LEMON/LEMON-official/lemon/euler.h - annotation
Load file history
Merge bugfix #420 to branch 1.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r964:141f9c0db4a3 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r633:7c12061bd271 r567:42d4b889903a r964:141f9c0db4a3 r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r964:141f9c0db4a3 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r606:c5fd2d996909 r567:42d4b889903a r567:42d4b889903a r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r567:42d4b889903a r606:c5fd2d996909 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r606:c5fd2d996909 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r606:c5fd2d996909 r639:2ebfdb89ec66 r567:42d4b889903a r638:493533ead9df r638:493533ead9df r638:493533ead9df r638:493533ead9df r638:493533ead9df r638:493533ead9df r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r638:493533ead9df r638:493533ead9df r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r633:7c12061bd271 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r964:141f9c0db4a3 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r964:141f9c0db4a3 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r606:c5fd2d996909 r567:42d4b889903a r567:42d4b889903a r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r606:c5fd2d996909 r567:42d4b889903a r606:c5fd2d996909 r639:2ebfdb89ec66 r606:c5fd2d996909 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r606:c5fd2d996909 r639:2ebfdb89ec66 r567:42d4b889903a r638:493533ead9df r638:493533ead9df r638:493533ead9df r638:493533ead9df r638:493533ead9df r638:493533ead9df r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r638:493533ead9df r639:2ebfdb89ec66 r638:493533ead9df r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r639:2ebfdb89ec66 r639:2ebfdb89ec66 r964:141f9c0db4a3 r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r695:4ff8041e9c2e r567:42d4b889903a r633:7c12061bd271 r695:4ff8041e9c2e r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r567:42d4b889903a r568:3af83b6be1df r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r639:2ebfdb89ec66 r606:c5fd2d996909 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r606:c5fd2d996909 r606:c5fd2d996909 r567:42d4b889903a r606:c5fd2d996909 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r606:c5fd2d996909 r606:c5fd2d996909 r567:42d4b889903a r606:c5fd2d996909 r567:42d4b889903a r606:c5fd2d996909 r567:42d4b889903a r639:2ebfdb89ec66 r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a r567:42d4b889903a | /* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_EULER_H
#define LEMON_EULER_H
#include<lemon/core.h>
#include<lemon/adaptors.h>
#include<lemon/connectivity.h>
#include <list>
/// \ingroup graph_properties
/// \file
/// \brief Euler tour iterators and a function for checking the \e Eulerian
/// property.
///
///This file provides Euler tour iterators and a function to check
///if a (di)graph is \e Eulerian.
namespace lemon {
///Euler tour iterator for digraphs.
/// \ingroup graph_prop
///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
///graph (if there exists) and it converts to the \c Arc type of the digraph.
///
///For example, if the given digraph has an Euler tour (i.e it has only one
///non-trivial component and the in-degree is equal to the out-degree
///for all nodes), then the following code will put the arcs of \c g
///to the vector \c et according to an Euler tour of \c g.
///\code
/// std::vector<ListDigraph::Arc> et;
/// for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
/// et.push_back(e);
///\endcode
///If \c g has no Euler tour, then the resulted walk will not be closed
///or not contain all arcs.
///\sa EulerIt
template<typename GR>
class DiEulerIt
{
typedef typename GR::Node Node;
typedef typename GR::NodeIt NodeIt;
typedef typename GR::Arc Arc;
typedef typename GR::ArcIt ArcIt;
typedef typename GR::OutArcIt OutArcIt;
typedef typename GR::InArcIt InArcIt;
const GR &g;
typename GR::template NodeMap<OutArcIt> narc;
std::list<Arc> euler;
public:
///Constructor
///Constructor.
///\param gr A digraph.
///\param start The starting point of the tour. If it is not given,
///the tour will start from the first node that has an outgoing arc.
DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
: g(gr), narc(g)
{
if (start==INVALID) {
NodeIt n(g);
while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
start=n;
}
if (start!=INVALID) {
for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
while (narc[start]!=INVALID) {
euler.push_back(narc[start]);
Node next=g.target(narc[start]);
++narc[start];
start=next;
}
}
}
///Arc conversion
operator Arc() { return euler.empty()?INVALID:euler.front(); }
///Compare with \c INVALID
bool operator==(Invalid) { return euler.empty(); }
///Compare with \c INVALID
bool operator!=(Invalid) { return !euler.empty(); }
///Next arc of the tour
///Next arc of the tour
///
DiEulerIt &operator++() {
Node s=g.target(euler.front());
euler.pop_front();
typename std::list<Arc>::iterator next=euler.begin();
while(narc[s]!=INVALID) {
euler.insert(next,narc[s]);
Node n=g.target(narc[s]);
++narc[s];
s=n;
}
return *this;
}
///Postfix incrementation
/// Postfix incrementation.
///
///\warning This incrementation
///returns an \c Arc, not a \ref DiEulerIt, as one may
///expect.
Arc operator++(int)
{
Arc e=*this;
++(*this);
return e;
}
};
///Euler tour iterator for graphs.
/// \ingroup graph_properties
///This iterator provides an Euler tour (Eulerian circuit) of an
///\e undirected graph (if there exists) and it converts to the \c Arc
///and \c Edge types of the graph.
///
///For example, if the given graph has an Euler tour (i.e it has only one
///non-trivial component and the degree of each node is even),
///the following code will print the arc IDs according to an
///Euler tour of \c g.
///\code
/// for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
/// std::cout << g.id(Edge(e)) << std::eol;
/// }
///\endcode
///Although this iterator is for undirected graphs, it still returns
///arcs in order to indicate the direction of the tour.
///(But arcs convert to edges, of course.)
///
///If \c g has no Euler tour, then the resulted walk will not be closed
///or not contain all edges.
template<typename GR>
class EulerIt
{
typedef typename GR::Node Node;
typedef typename GR::NodeIt NodeIt;
typedef typename GR::Arc Arc;
typedef typename GR::Edge Edge;
typedef typename GR::ArcIt ArcIt;
typedef typename GR::OutArcIt OutArcIt;
typedef typename GR::InArcIt InArcIt;
const GR &g;
typename GR::template NodeMap<OutArcIt> narc;
typename GR::template EdgeMap<bool> visited;
std::list<Arc> euler;
public:
///Constructor
///Constructor.
///\param gr A graph.
///\param start The starting point of the tour. If it is not given,
///the tour will start from the first node that has an incident edge.
EulerIt(const GR &gr, typename GR::Node start = INVALID)
: g(gr), narc(g), visited(g, false)
{
if (start==INVALID) {
NodeIt n(g);
while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
start=n;
}
if (start!=INVALID) {
for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
while(narc[start]!=INVALID) {
euler.push_back(narc[start]);
visited[narc[start]]=true;
Node next=g.target(narc[start]);
++narc[start];
start=next;
while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
}
}
}
///Arc conversion
operator Arc() const { return euler.empty()?INVALID:euler.front(); }
///Edge conversion
operator Edge() const { return euler.empty()?INVALID:euler.front(); }
///Compare with \c INVALID
bool operator==(Invalid) const { return euler.empty(); }
///Compare with \c INVALID
bool operator!=(Invalid) const { return !euler.empty(); }
///Next arc of the tour
///Next arc of the tour
///
EulerIt &operator++() {
Node s=g.target(euler.front());
euler.pop_front();
typename std::list<Arc>::iterator next=euler.begin();
while(narc[s]!=INVALID) {
while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
if(narc[s]==INVALID) break;
else {
euler.insert(next,narc[s]);
visited[narc[s]]=true;
Node n=g.target(narc[s]);
++narc[s];
s=n;
}
}
return *this;
}
///Postfix incrementation
/// Postfix incrementation.
///
///\warning This incrementation returns an \c Arc (which converts to
///an \c Edge), not an \ref EulerIt, as one may expect.
Arc operator++(int)
{
Arc e=*this;
++(*this);
return e;
}
};
///Check if the given graph is Eulerian
/// \ingroup graph_properties
///This function checks if the given graph is Eulerian.
///It works for both directed and undirected graphs.
///
///By definition, a digraph is called \e Eulerian if
///and only if it is connected and the number of incoming and outgoing
///arcs are the same for each node.
///Similarly, an undirected graph is called \e Eulerian if
///and only if it is connected and the number of incident edges is even
///for each node.
///
///\note There are (di)graphs that are not Eulerian, but still have an
/// Euler tour, since they may contain isolated nodes.
///
///\sa DiEulerIt, EulerIt
template<typename GR>
#ifdef DOXYGEN
bool
#else
typename enable_if<UndirectedTagIndicator<GR>,bool>::type
eulerian(const GR &g)
{
for(typename GR::NodeIt n(g);n!=INVALID;++n)
if(countIncEdges(g,n)%2) return false;
return connected(g);
}
template<class GR>
typename disable_if<UndirectedTagIndicator<GR>,bool>::type
#endif
eulerian(const GR &g)
{
for(typename GR::NodeIt n(g);n!=INVALID;++n)
if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
return connected(undirector(g));
}
}
#endif
|