lemon/euler.h
author deba
Tue, 07 Feb 2006 09:20:47 +0000
changeset 1965 71b3bc042c47
parent 1909 2d806130e700
child 1970 bd88ea06ab69
permissions -rw-r--r--
Compilation with G++ -ansi
alpar@1738
     1
/* -*- C++ -*-
alpar@1738
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1738
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@1738
     8
 *
alpar@1738
     9
 * Permission to use, modify and distribute this software is granted
alpar@1738
    10
 * provided that this copyright notice appears in all copies. For
alpar@1738
    11
 * precise terms see the accompanying LICENSE file.
alpar@1738
    12
 *
alpar@1738
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@1738
    14
 * express or implied, and with no claim as to its suitability for any
alpar@1738
    15
 * purpose.
alpar@1738
    16
 *
alpar@1738
    17
 */
alpar@1956
    18
alpar@1738
    19
#include<lemon/invalid.h>
alpar@1818
    20
#include<lemon/topology.h>
alpar@1738
    21
#include <list>
alpar@1738
    22
deba@1769
    23
/// \ingroup topology
alpar@1738
    24
/// \file
alpar@1738
    25
/// \brief Euler tour
alpar@1738
    26
///
alpar@1738
    27
///This file provides an Euler tour iterator and ways to check
alpar@1738
    28
///if a graph is euler.
alpar@1738
    29
alpar@1738
    30
alpar@1738
    31
namespace lemon {
alpar@1738
    32
alpar@1818
    33
  ///Euler iterator for directed graphs.
alpar@1738
    34
deba@1769
    35
  /// \ingroup topology
alpar@1738
    36
  ///This iterator converts to the \c Edge type of the graph and using
alpar@1803
    37
  ///operator ++ it provides an Euler tour of the graph (if there exists).
alpar@1738
    38
  ///
alpar@1738
    39
  ///For example
alpar@1738
    40
  ///if the given graph if Euler (i.e it has only one nontrivial component
alpar@1738
    41
  ///and the in-degree is equal to the out-degree for all nodes),
alpar@1803
    42
  ///the following code will print the edge IDs according to an
alpar@1738
    43
  ///Euler tour of \c g.
alpar@1738
    44
  ///\code
alpar@1738
    45
  ///  for(EulerIt<ListGraph> e(g),e!=INVALID;++e) {
alpar@1738
    46
  ///    std::cout << g.id(e) << std::eol;
alpar@1738
    47
  ///  }
alpar@1738
    48
  ///\endcode
alpar@1738
    49
  ///If \c g is not Euler then the resulted tour will not be full or closed.
alpar@1738
    50
  ///\todo Test required
alpar@1738
    51
  template<class Graph>
alpar@1738
    52
  class EulerIt 
alpar@1738
    53
  {
alpar@1738
    54
    typedef typename Graph::Node Node;
alpar@1738
    55
    typedef typename Graph::NodeIt NodeIt;
alpar@1738
    56
    typedef typename Graph::Edge Edge;
alpar@1738
    57
    typedef typename Graph::EdgeIt EdgeIt;
alpar@1738
    58
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1738
    59
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1738
    60
    
alpar@1738
    61
    const Graph &g;
alpar@1738
    62
    typename Graph::NodeMap<OutEdgeIt> nedge;
alpar@1738
    63
    std::list<Edge> euler;
alpar@1738
    64
alpar@1738
    65
  public:
alpar@1738
    66
    
alpar@1738
    67
    ///Constructor
alpar@1738
    68
alpar@1738
    69
    ///\param _g A directed graph.
alpar@1738
    70
    ///\param start The starting point of the tour. If it is not given
alpar@1803
    71
    ///       the tour will start from the first node.
alpar@1738
    72
    EulerIt(const Graph &_g,typename Graph::Node start=INVALID)
alpar@1738
    73
      : g(_g), nedge(g)
alpar@1738
    74
    {
alpar@1738
    75
      if(start==INVALID) start=NodeIt(g);
alpar@1738
    76
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n);
alpar@1738
    77
      while(nedge[start]!=INVALID) {
alpar@1738
    78
	euler.push_back(nedge[start]);
alpar@1738
    79
	Node next=g.target(nedge[start]);
alpar@1738
    80
	++nedge[start];
alpar@1738
    81
	start=next;
alpar@1738
    82
      }
alpar@1738
    83
    }
alpar@1738
    84
    
alpar@1738
    85
    ///Edge Conversion
alpar@1738
    86
    operator Edge() { return euler.empty()?INVALID:euler.front(); }
alpar@1738
    87
    bool operator==(Invalid) { return euler.empty(); }
alpar@1738
    88
    bool operator!=(Invalid) { return !euler.empty(); }
alpar@1738
    89
    
alpar@1738
    90
    ///Next edge of the tour
alpar@1738
    91
    EulerIt &operator++() {
alpar@1738
    92
      Node s=g.target(euler.front());
alpar@1738
    93
      euler.pop_front();
alpar@1738
    94
      //This produces a warning.Strange.
alpar@1738
    95
      //std::list<Edge>::iterator next=euler.begin();
alpar@1738
    96
      typename std::list<Edge>::iterator next=euler.begin();
alpar@1738
    97
      while(nedge[s]!=INVALID) {
alpar@1738
    98
	euler.insert(next,nedge[s]);
alpar@1738
    99
	Node n=g.target(nedge[s]);
alpar@1738
   100
	++nedge[s];
alpar@1738
   101
	s=n;
alpar@1738
   102
      }
alpar@1738
   103
      return *this;
alpar@1738
   104
    }
alpar@1738
   105
    ///Postfix incrementation
alpar@1738
   106
    
alpar@1803
   107
    ///\warning This incrementation
alpar@1803
   108
    ///returns an \c Edge, not an \ref EulerIt, as one may
alpar@1803
   109
    ///expect.
alpar@1738
   110
    Edge operator++(int) 
alpar@1738
   111
    {
alpar@1738
   112
      Edge e=*this;
alpar@1738
   113
      ++(*this);
alpar@1738
   114
      return e;
alpar@1738
   115
    }
alpar@1738
   116
  };
alpar@1738
   117
alpar@1818
   118
  ///Euler iterator for undirected graphs.
alpar@1818
   119
alpar@1818
   120
  /// \ingroup topology
alpar@1818
   121
  ///This iterator converts to the \c Edge type of the graph and using
alpar@1818
   122
  ///operator ++ it provides an Euler tour of the graph (if there exists).
alpar@1818
   123
  ///
alpar@1818
   124
  ///For example
alpar@1818
   125
  ///if the given graph if Euler (i.e it has only one nontrivial component
alpar@1818
   126
  ///and the degree of each node is even),
alpar@1818
   127
  ///the following code will print the edge IDs according to an
alpar@1818
   128
  ///Euler tour of \c g.
alpar@1818
   129
  ///\code
klao@1909
   130
  ///  for(UEulerIt<ListUGraph> e(g),e!=INVALID;++e) {
klao@1909
   131
  ///    std::cout << g.id(UEdge(e)) << std::eol;
alpar@1818
   132
  ///  }
alpar@1818
   133
  ///\endcode
alpar@1818
   134
  ///Although the iterator provides an Euler tour of an undirected graph,
klao@1909
   135
  ///in order to indicate the direction of the tour, UEulerIt
alpar@1818
   136
  ///returns directed edges (that convert to the undirected ones, of course).
alpar@1818
   137
  ///
alpar@1818
   138
  ///If \c g is not Euler then the resulted tour will not be full or closed.
alpar@1818
   139
  ///\todo Test required
alpar@1818
   140
  template<class Graph>
klao@1909
   141
  class UEulerIt
alpar@1818
   142
  {
alpar@1818
   143
    typedef typename Graph::Node Node;
alpar@1818
   144
    typedef typename Graph::NodeIt NodeIt;
alpar@1818
   145
    typedef typename Graph::Edge Edge;
alpar@1818
   146
    typedef typename Graph::EdgeIt EdgeIt;
alpar@1818
   147
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1818
   148
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1818
   149
    
alpar@1818
   150
    const Graph &g;
alpar@1818
   151
    typename Graph::NodeMap<OutEdgeIt> nedge;
klao@1909
   152
    typename Graph::UEdgeMap<bool> visited;
alpar@1818
   153
    std::list<Edge> euler;
alpar@1818
   154
alpar@1818
   155
  public:
alpar@1818
   156
    
alpar@1818
   157
    ///Constructor
alpar@1818
   158
alpar@1818
   159
    ///\param _g An undirected graph.
alpar@1818
   160
    ///\param start The starting point of the tour. If it is not given
alpar@1818
   161
    ///       the tour will start from the first node.
klao@1909
   162
    UEulerIt(const Graph &_g,typename Graph::Node start=INVALID)
alpar@1818
   163
      : g(_g), nedge(g), visited(g,false)
alpar@1818
   164
    {
alpar@1818
   165
      if(start==INVALID) start=NodeIt(g);
alpar@1818
   166
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n);
alpar@1818
   167
      while(nedge[start]!=INVALID) {
alpar@1818
   168
	euler.push_back(nedge[start]);
alpar@1818
   169
	Node next=g.target(nedge[start]);
alpar@1818
   170
	++nedge[start];
alpar@1818
   171
	start=next;	while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
alpar@1818
   172
      }
alpar@1818
   173
    }
alpar@1818
   174
    
alpar@1818
   175
    ///Edge Conversion
alpar@1818
   176
    operator Edge() { return euler.empty()?INVALID:euler.front(); }
alpar@1818
   177
    bool operator==(Invalid) { return euler.empty(); }
alpar@1818
   178
    bool operator!=(Invalid) { return !euler.empty(); }
alpar@1818
   179
    
alpar@1818
   180
    ///Next edge of the tour
klao@1909
   181
    UEulerIt &operator++() {
alpar@1818
   182
      Node s=g.target(euler.front());
alpar@1818
   183
      euler.pop_front();
alpar@1818
   184
      typename std::list<Edge>::iterator next=euler.begin();
alpar@1818
   185
alpar@1818
   186
      while(nedge[s]!=INVALID) {
alpar@1818
   187
	while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
alpar@1818
   188
	if(nedge[s]==INVALID) break;
alpar@1818
   189
	else {
alpar@1818
   190
	  euler.insert(next,nedge[s]);
alpar@1818
   191
	  Node n=g.target(nedge[s]);
alpar@1818
   192
	  ++nedge[s];
alpar@1818
   193
	  s=n;
alpar@1818
   194
	}
alpar@1818
   195
      }
alpar@1818
   196
      return *this;
alpar@1818
   197
    }
alpar@1818
   198
    
alpar@1818
   199
    ///Postfix incrementation
alpar@1818
   200
    
alpar@1818
   201
    ///\warning This incrementation
klao@1909
   202
    ///returns an \c Edge, not an \ref UEulerIt, as one may
alpar@1818
   203
    ///expect.
alpar@1818
   204
    Edge operator++(int) 
alpar@1818
   205
    {
alpar@1818
   206
      Edge e=*this;
alpar@1818
   207
      ++(*this);
alpar@1818
   208
      return e;
alpar@1818
   209
    }
alpar@1818
   210
  };
alpar@1818
   211
alpar@1818
   212
alpar@1738
   213
  ///Checks if the graph is Euler
alpar@1738
   214
alpar@1818
   215
  /// \ingroup topology
alpar@1738
   216
  ///Checks if the graph is Euler. It works for both directed and
alpar@1738
   217
  ///undirected graphs.
alpar@1818
   218
  ///\note By definition, a directed graph is called \e Euler if
alpar@1818
   219
  ///and only if connected and the number of it is incoming and outgoing edges
alpar@1818
   220
  ///are the same for each node.
alpar@1818
   221
  ///Similarly, an undirected graph is called \e Euler if
alpar@1818
   222
  ///and only if it is connected and the number of incident edges is even
alpar@1818
   223
  ///for each node. <em>Therefore, there are graphs which are not Euler, but
alpar@1818
   224
  ///still have an Euler tour</em>.
alpar@1738
   225
  ///\todo Test required
alpar@1738
   226
  template<class Graph>
alpar@1738
   227
#ifdef DOXYGEN
alpar@1738
   228
  bool
alpar@1738
   229
#else
klao@1909
   230
  typename enable_if<typename Graph::UTag,bool>::type
alpar@1818
   231
  euler(const Graph &g) 
alpar@1818
   232
  {
alpar@1818
   233
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1818
   234
      if(countIncEdges(g,n)%2) return false;
alpar@1818
   235
    return connected(g);
alpar@1818
   236
  }
alpar@1818
   237
  template<class Graph>
klao@1909
   238
  typename disable_if<typename Graph::UTag,bool>::type
alpar@1738
   239
#endif
alpar@1738
   240
  euler(const Graph &g) 
alpar@1738
   241
  {
alpar@1738
   242
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1738
   243
      if(countInEdges(g,n)!=countOutEdges(g,n)) return false;
alpar@1818
   244
    return connected(g);
alpar@1738
   245
  }
alpar@1738
   246
  
alpar@1738
   247
}