lemon/euler.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1970 bd88ea06ab69
child 1993 2115143eceea
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
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@1970
    37
  ///operator ++ it provides an Euler tour of a \e directed
alpar@1970
    38
  ///graph (if there exists).
alpar@1738
    39
  ///
alpar@1738
    40
  ///For example
alpar@1738
    41
  ///if the given graph if Euler (i.e it has only one nontrivial component
alpar@1738
    42
  ///and the in-degree is equal to the out-degree for all nodes),
alpar@1970
    43
  ///the following code will put the edges of \c g
alpar@1970
    44
  ///to the vector \c et according to an
alpar@1738
    45
  ///Euler tour of \c g.
alpar@1738
    46
  ///\code
alpar@1970
    47
  ///  std::vector<ListGraph::Edge> et;
alpar@1970
    48
  ///  for(EulerIt<ListGraph> e(g),e!=INVALID;++e)
alpar@1970
    49
  ///    et.push_back(e);
alpar@1738
    50
  ///\endcode
alpar@1738
    51
  ///If \c g is not Euler then the resulted tour will not be full or closed.
alpar@1970
    52
  ///\sa UEulerIt
alpar@1738
    53
  ///\todo Test required
alpar@1738
    54
  template<class Graph>
alpar@1738
    55
  class EulerIt 
alpar@1738
    56
  {
alpar@1738
    57
    typedef typename Graph::Node Node;
alpar@1738
    58
    typedef typename Graph::NodeIt NodeIt;
alpar@1738
    59
    typedef typename Graph::Edge Edge;
alpar@1738
    60
    typedef typename Graph::EdgeIt EdgeIt;
alpar@1738
    61
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1738
    62
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1738
    63
    
alpar@1738
    64
    const Graph &g;
alpar@1738
    65
    typename Graph::NodeMap<OutEdgeIt> nedge;
alpar@1738
    66
    std::list<Edge> euler;
alpar@1738
    67
alpar@1738
    68
  public:
alpar@1738
    69
    
alpar@1738
    70
    ///Constructor
alpar@1738
    71
alpar@1738
    72
    ///\param _g A directed graph.
alpar@1738
    73
    ///\param start The starting point of the tour. If it is not given
alpar@1803
    74
    ///       the tour will start from the first node.
alpar@1738
    75
    EulerIt(const Graph &_g,typename Graph::Node start=INVALID)
alpar@1738
    76
      : g(_g), nedge(g)
alpar@1738
    77
    {
alpar@1738
    78
      if(start==INVALID) start=NodeIt(g);
alpar@1738
    79
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n);
alpar@1738
    80
      while(nedge[start]!=INVALID) {
alpar@1738
    81
	euler.push_back(nedge[start]);
alpar@1738
    82
	Node next=g.target(nedge[start]);
alpar@1738
    83
	++nedge[start];
alpar@1738
    84
	start=next;
alpar@1738
    85
      }
alpar@1738
    86
    }
alpar@1738
    87
    
alpar@1738
    88
    ///Edge Conversion
alpar@1738
    89
    operator Edge() { return euler.empty()?INVALID:euler.front(); }
alpar@1738
    90
    bool operator==(Invalid) { return euler.empty(); }
alpar@1738
    91
    bool operator!=(Invalid) { return !euler.empty(); }
alpar@1738
    92
    
alpar@1738
    93
    ///Next edge of the tour
alpar@1738
    94
    EulerIt &operator++() {
alpar@1738
    95
      Node s=g.target(euler.front());
alpar@1738
    96
      euler.pop_front();
alpar@1738
    97
      //This produces a warning.Strange.
alpar@1738
    98
      //std::list<Edge>::iterator next=euler.begin();
alpar@1738
    99
      typename std::list<Edge>::iterator next=euler.begin();
alpar@1738
   100
      while(nedge[s]!=INVALID) {
alpar@1738
   101
	euler.insert(next,nedge[s]);
alpar@1738
   102
	Node n=g.target(nedge[s]);
alpar@1738
   103
	++nedge[s];
alpar@1738
   104
	s=n;
alpar@1738
   105
      }
alpar@1738
   106
      return *this;
alpar@1738
   107
    }
alpar@1738
   108
    ///Postfix incrementation
alpar@1738
   109
    
alpar@1803
   110
    ///\warning This incrementation
alpar@1803
   111
    ///returns an \c Edge, not an \ref EulerIt, as one may
alpar@1803
   112
    ///expect.
alpar@1738
   113
    Edge operator++(int) 
alpar@1738
   114
    {
alpar@1738
   115
      Edge e=*this;
alpar@1738
   116
      ++(*this);
alpar@1738
   117
      return e;
alpar@1738
   118
    }
alpar@1738
   119
  };
alpar@1738
   120
alpar@1818
   121
  ///Euler iterator for undirected graphs.
alpar@1818
   122
alpar@1818
   123
  /// \ingroup topology
alpar@1970
   124
  ///This iterator converts to the \c Edge (or \cUEdge)
alpar@1970
   125
  ///type of the graph and using
alpar@1970
   126
  ///operator ++ it provides an Euler tour of an \undirected
alpar@1970
   127
  ///graph (if there exists).
alpar@1818
   128
  ///
alpar@1818
   129
  ///For example
alpar@1818
   130
  ///if the given graph if Euler (i.e it has only one nontrivial component
alpar@1818
   131
  ///and the degree of each node is even),
alpar@1818
   132
  ///the following code will print the edge IDs according to an
alpar@1818
   133
  ///Euler tour of \c g.
alpar@1818
   134
  ///\code
klao@1909
   135
  ///  for(UEulerIt<ListUGraph> e(g),e!=INVALID;++e) {
klao@1909
   136
  ///    std::cout << g.id(UEdge(e)) << std::eol;
alpar@1818
   137
  ///  }
alpar@1818
   138
  ///\endcode
alpar@1818
   139
  ///Although the iterator provides an Euler tour of an undirected graph,
klao@1909
   140
  ///in order to indicate the direction of the tour, UEulerIt
alpar@1818
   141
  ///returns directed edges (that convert to the undirected ones, of course).
alpar@1818
   142
  ///
alpar@1818
   143
  ///If \c g is not Euler then the resulted tour will not be full or closed.
alpar@1970
   144
  ///\sa EulerIt
alpar@1818
   145
  ///\todo Test required
alpar@1818
   146
  template<class Graph>
klao@1909
   147
  class UEulerIt
alpar@1818
   148
  {
alpar@1818
   149
    typedef typename Graph::Node Node;
alpar@1818
   150
    typedef typename Graph::NodeIt NodeIt;
alpar@1818
   151
    typedef typename Graph::Edge Edge;
alpar@1818
   152
    typedef typename Graph::EdgeIt EdgeIt;
alpar@1818
   153
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1818
   154
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1818
   155
    
alpar@1818
   156
    const Graph &g;
alpar@1818
   157
    typename Graph::NodeMap<OutEdgeIt> nedge;
klao@1909
   158
    typename Graph::UEdgeMap<bool> visited;
alpar@1818
   159
    std::list<Edge> euler;
alpar@1818
   160
alpar@1818
   161
  public:
alpar@1818
   162
    
alpar@1818
   163
    ///Constructor
alpar@1818
   164
alpar@1818
   165
    ///\param _g An undirected graph.
alpar@1818
   166
    ///\param start The starting point of the tour. If it is not given
alpar@1818
   167
    ///       the tour will start from the first node.
klao@1909
   168
    UEulerIt(const Graph &_g,typename Graph::Node start=INVALID)
alpar@1818
   169
      : g(_g), nedge(g), visited(g,false)
alpar@1818
   170
    {
alpar@1818
   171
      if(start==INVALID) start=NodeIt(g);
alpar@1818
   172
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n);
alpar@1818
   173
      while(nedge[start]!=INVALID) {
alpar@1818
   174
	euler.push_back(nedge[start]);
alpar@1818
   175
	Node next=g.target(nedge[start]);
alpar@1818
   176
	++nedge[start];
alpar@1818
   177
	start=next;	while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
alpar@1818
   178
      }
alpar@1818
   179
    }
alpar@1818
   180
    
alpar@1818
   181
    ///Edge Conversion
alpar@1818
   182
    operator Edge() { return euler.empty()?INVALID:euler.front(); }
alpar@1818
   183
    bool operator==(Invalid) { return euler.empty(); }
alpar@1818
   184
    bool operator!=(Invalid) { return !euler.empty(); }
alpar@1818
   185
    
alpar@1818
   186
    ///Next edge of the tour
klao@1909
   187
    UEulerIt &operator++() {
alpar@1818
   188
      Node s=g.target(euler.front());
alpar@1818
   189
      euler.pop_front();
alpar@1818
   190
      typename std::list<Edge>::iterator next=euler.begin();
alpar@1818
   191
alpar@1818
   192
      while(nedge[s]!=INVALID) {
alpar@1818
   193
	while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
alpar@1818
   194
	if(nedge[s]==INVALID) break;
alpar@1818
   195
	else {
alpar@1818
   196
	  euler.insert(next,nedge[s]);
alpar@1818
   197
	  Node n=g.target(nedge[s]);
alpar@1818
   198
	  ++nedge[s];
alpar@1818
   199
	  s=n;
alpar@1818
   200
	}
alpar@1818
   201
      }
alpar@1818
   202
      return *this;
alpar@1818
   203
    }
alpar@1818
   204
    
alpar@1818
   205
    ///Postfix incrementation
alpar@1818
   206
    
alpar@1818
   207
    ///\warning This incrementation
klao@1909
   208
    ///returns an \c Edge, not an \ref UEulerIt, as one may
alpar@1818
   209
    ///expect.
alpar@1818
   210
    Edge operator++(int) 
alpar@1818
   211
    {
alpar@1818
   212
      Edge e=*this;
alpar@1818
   213
      ++(*this);
alpar@1818
   214
      return e;
alpar@1818
   215
    }
alpar@1818
   216
  };
alpar@1818
   217
alpar@1818
   218
alpar@1738
   219
  ///Checks if the graph is Euler
alpar@1738
   220
alpar@1818
   221
  /// \ingroup topology
alpar@1738
   222
  ///Checks if the graph is Euler. It works for both directed and
alpar@1738
   223
  ///undirected graphs.
alpar@1818
   224
  ///\note By definition, a directed graph is called \e Euler if
alpar@1818
   225
  ///and only if connected and the number of it is incoming and outgoing edges
alpar@1818
   226
  ///are the same for each node.
alpar@1818
   227
  ///Similarly, an undirected graph is called \e Euler if
alpar@1818
   228
  ///and only if it is connected and the number of incident edges is even
alpar@1818
   229
  ///for each node. <em>Therefore, there are graphs which are not Euler, but
alpar@1818
   230
  ///still have an Euler tour</em>.
alpar@1738
   231
  ///\todo Test required
alpar@1738
   232
  template<class Graph>
alpar@1738
   233
#ifdef DOXYGEN
alpar@1738
   234
  bool
alpar@1738
   235
#else
deba@1979
   236
  typename enable_if<UndirectedTagIndicator<Graph>,bool>::type
alpar@1818
   237
  euler(const Graph &g) 
alpar@1818
   238
  {
alpar@1818
   239
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1818
   240
      if(countIncEdges(g,n)%2) return false;
alpar@1818
   241
    return connected(g);
alpar@1818
   242
  }
alpar@1818
   243
  template<class Graph>
deba@1979
   244
  typename disable_if<UndirectedTagIndicator<Graph>,bool>::type
alpar@1738
   245
#endif
alpar@1738
   246
  euler(const Graph &g) 
alpar@1738
   247
  {
alpar@1738
   248
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1738
   249
      if(countInEdges(g,n)!=countOutEdges(g,n)) return false;
alpar@1818
   250
    return connected(g);
alpar@1738
   251
  }
alpar@1738
   252
  
alpar@1738
   253
}