lemon/euler.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 596 8c3112a66878
parent 505 3af83b6be1df
child 550 c5fd2d996909
permissions -rw-r--r--
Use XTI implementation instead of ATI in NetworkSimplex (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

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