lemon/euler.h
author deba
Thu, 17 Nov 2005 10:46:38 +0000
changeset 1813 5c5d1574667d
parent 1769 a67ec111236c
child 1818 8f9905c4e1c1
permissions -rw-r--r--
Bug fix
alpar@1738
     1
/* -*- C++ -*-
alpar@1738
     2
 * lemon/topology.h - Part of LEMON, a generic C++ optimization library
alpar@1738
     3
 *
alpar@1738
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1738
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@1738
     6
 *
alpar@1738
     7
 * Permission to use, modify and distribute this software is granted
alpar@1738
     8
 * provided that this copyright notice appears in all copies. For
alpar@1738
     9
 * precise terms see the accompanying LICENSE file.
alpar@1738
    10
 *
alpar@1738
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@1738
    12
 * express or implied, and with no claim as to its suitability for any
alpar@1738
    13
 * purpose.
alpar@1738
    14
 *
alpar@1738
    15
 */
alpar@1738
    16
#include<lemon/invalid.h>
alpar@1738
    17
#include <list>
alpar@1738
    18
deba@1769
    19
/// \ingroup topology
alpar@1738
    20
/// \file
alpar@1738
    21
/// \brief Euler tour
alpar@1738
    22
///
alpar@1738
    23
///This file provides an Euler tour iterator and ways to check
alpar@1738
    24
///if a graph is euler.
alpar@1738
    25
alpar@1738
    26
alpar@1738
    27
namespace lemon {
alpar@1738
    28
alpar@1738
    29
  ///Euler iterator in directed graphs.
alpar@1738
    30
deba@1769
    31
  /// \ingroup topology
alpar@1738
    32
  ///This iterator converts to the \c Edge type of the graph and using
alpar@1803
    33
  ///operator ++ it provides an Euler tour of the graph (if there exists).
alpar@1738
    34
  ///
alpar@1738
    35
  ///For example
alpar@1738
    36
  ///if the given graph if Euler (i.e it has only one nontrivial component
alpar@1738
    37
  ///and the in-degree is equal to the out-degree for all nodes),
alpar@1803
    38
  ///the following code will print the edge IDs according to an
alpar@1738
    39
  ///Euler tour of \c g.
alpar@1738
    40
  ///\code
alpar@1738
    41
  ///  for(EulerIt<ListGraph> e(g),e!=INVALID;++e) {
alpar@1738
    42
  ///    std::cout << g.id(e) << std::eol;
alpar@1738
    43
  ///  }
alpar@1738
    44
  ///\endcode
alpar@1738
    45
  ///If \c g is not Euler then the resulted tour will not be full or closed.
alpar@1738
    46
  ///\todo Test required
alpar@1738
    47
  template<class Graph>
alpar@1738
    48
  class EulerIt 
alpar@1738
    49
  {
alpar@1738
    50
    typedef typename Graph::Node Node;
alpar@1738
    51
    typedef typename Graph::NodeIt NodeIt;
alpar@1738
    52
    typedef typename Graph::Edge Edge;
alpar@1738
    53
    typedef typename Graph::EdgeIt EdgeIt;
alpar@1738
    54
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1738
    55
    typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1738
    56
    
alpar@1738
    57
    const Graph &g;
alpar@1738
    58
    typename Graph::NodeMap<OutEdgeIt> nedge;
alpar@1738
    59
    std::list<Edge> euler;
alpar@1738
    60
alpar@1738
    61
  public:
alpar@1738
    62
    
alpar@1738
    63
    ///Constructor
alpar@1738
    64
alpar@1738
    65
    ///\param _g A directed graph.
alpar@1738
    66
    ///\param start The starting point of the tour. If it is not given
alpar@1803
    67
    ///       the tour will start from the first node.
alpar@1738
    68
    EulerIt(const Graph &_g,typename Graph::Node start=INVALID)
alpar@1738
    69
      : g(_g), nedge(g)
alpar@1738
    70
    {
alpar@1738
    71
      if(start==INVALID) start=NodeIt(g);
alpar@1738
    72
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n);
alpar@1738
    73
      while(nedge[start]!=INVALID) {
alpar@1738
    74
	euler.push_back(nedge[start]);
alpar@1738
    75
	Node next=g.target(nedge[start]);
alpar@1738
    76
	++nedge[start];
alpar@1738
    77
	start=next;
alpar@1738
    78
      }
alpar@1738
    79
    }
alpar@1738
    80
    
alpar@1738
    81
    ///Edge Conversion
alpar@1738
    82
    operator Edge() { return euler.empty()?INVALID:euler.front(); }
alpar@1738
    83
    bool operator==(Invalid) { return euler.empty(); }
alpar@1738
    84
    bool operator!=(Invalid) { return !euler.empty(); }
alpar@1738
    85
    
alpar@1738
    86
    ///Next edge of the tour
alpar@1738
    87
    EulerIt &operator++() {
alpar@1738
    88
      Node s=g.target(euler.front());
alpar@1738
    89
      euler.pop_front();
alpar@1738
    90
      //This produces a warning.Strange.
alpar@1738
    91
      //std::list<Edge>::iterator next=euler.begin();
alpar@1738
    92
      typename std::list<Edge>::iterator next=euler.begin();
alpar@1738
    93
      while(nedge[s]!=INVALID) {
alpar@1738
    94
	euler.insert(next,nedge[s]);
alpar@1738
    95
	Node n=g.target(nedge[s]);
alpar@1738
    96
	++nedge[s];
alpar@1738
    97
	s=n;
alpar@1738
    98
      }
alpar@1738
    99
      return *this;
alpar@1738
   100
    }
alpar@1738
   101
    ///Postfix incrementation
alpar@1738
   102
    
alpar@1803
   103
    ///\warning This incrementation
alpar@1803
   104
    ///returns an \c Edge, not an \ref EulerIt, as one may
alpar@1803
   105
    ///expect.
alpar@1738
   106
    Edge operator++(int) 
alpar@1738
   107
    {
alpar@1738
   108
      Edge e=*this;
alpar@1738
   109
      ++(*this);
alpar@1738
   110
      return e;
alpar@1738
   111
    }
alpar@1738
   112
  };
alpar@1738
   113
alpar@1738
   114
  ///Checks if the graph is Euler
alpar@1738
   115
alpar@1738
   116
  /// \ingroup gutils
alpar@1738
   117
  ///Checks if the graph is Euler. It works for both directed and
alpar@1738
   118
  ///undirected graphs.
alpar@1738
   119
  ///\todo Test required
alpar@1738
   120
  template<class Graph>
alpar@1738
   121
#ifdef DOXYGEN
alpar@1738
   122
  bool
alpar@1738
   123
#else
alpar@1738
   124
  typename enable_if<typename Graph::UndirTag,bool>::type
alpar@1738
   125
#endif
alpar@1738
   126
  euler(const Graph &g) 
alpar@1738
   127
  {
alpar@1738
   128
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1738
   129
      if(countIncEdges(g,n)%2) return false;
alpar@1738
   130
    return true;
alpar@1738
   131
  }
alpar@1738
   132
  template<class Graph>
alpar@1738
   133
  typename disable_if<typename Graph::UndirTag,bool>::type
deba@1761
   134
  euler(const Graph &g) 
alpar@1738
   135
  {
alpar@1738
   136
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1738
   137
      if(countInEdges(g,n)!=countOutEdges(g,n)) return false;
alpar@1738
   138
    return true;
alpar@1738
   139
  }
alpar@1738
   140
  
alpar@1738
   141
}