lemon/static_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 787 c2230649a493
child 1124 d51126dc39fa
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
alpar@877
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@773
     2
 *
alpar@877
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@773
     4
 *
alpar@877
     5
 * Copyright (C) 2003-2010
kpeter@773
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@773
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@773
     8
 *
kpeter@773
     9
 * Permission to use, modify and distribute this software is granted
kpeter@773
    10
 * provided that this copyright notice appears in all copies. For
kpeter@773
    11
 * precise terms see the accompanying LICENSE file.
kpeter@773
    12
 *
kpeter@773
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@773
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@773
    15
 * purpose.
kpeter@773
    16
 *
kpeter@773
    17
 */
kpeter@773
    18
kpeter@773
    19
#ifndef LEMON_STATIC_GRAPH_H
kpeter@773
    20
#define LEMON_STATIC_GRAPH_H
kpeter@773
    21
kpeter@773
    22
///\ingroup graphs
kpeter@773
    23
///\file
kpeter@773
    24
///\brief StaticDigraph class.
kpeter@773
    25
kpeter@773
    26
#include <lemon/core.h>
kpeter@773
    27
#include <lemon/bits/graph_extender.h>
kpeter@773
    28
kpeter@773
    29
namespace lemon {
kpeter@773
    30
kpeter@773
    31
  class StaticDigraphBase {
kpeter@773
    32
  public:
kpeter@773
    33
alpar@877
    34
    StaticDigraphBase()
alpar@877
    35
      : built(false), node_num(0), arc_num(0),
kpeter@773
    36
        node_first_out(NULL), node_first_in(NULL),
alpar@877
    37
        arc_source(NULL), arc_target(NULL),
kpeter@773
    38
        arc_next_in(NULL), arc_next_out(NULL) {}
alpar@877
    39
kpeter@773
    40
    ~StaticDigraphBase() {
kpeter@774
    41
      if (built) {
kpeter@773
    42
        delete[] node_first_out;
kpeter@773
    43
        delete[] node_first_in;
kpeter@773
    44
        delete[] arc_source;
kpeter@773
    45
        delete[] arc_target;
kpeter@773
    46
        delete[] arc_next_out;
kpeter@773
    47
        delete[] arc_next_in;
kpeter@773
    48
      }
kpeter@773
    49
    }
kpeter@773
    50
kpeter@773
    51
    class Node {
kpeter@773
    52
      friend class StaticDigraphBase;
kpeter@773
    53
    protected:
kpeter@773
    54
      int id;
kpeter@773
    55
      Node(int _id) : id(_id) {}
kpeter@773
    56
    public:
kpeter@773
    57
      Node() {}
kpeter@773
    58
      Node (Invalid) : id(-1) {}
kpeter@773
    59
      bool operator==(const Node& node) const { return id == node.id; }
kpeter@773
    60
      bool operator!=(const Node& node) const { return id != node.id; }
kpeter@773
    61
      bool operator<(const Node& node) const { return id < node.id; }
kpeter@773
    62
    };
kpeter@773
    63
kpeter@773
    64
    class Arc {
alpar@877
    65
      friend class StaticDigraphBase;
kpeter@773
    66
    protected:
kpeter@773
    67
      int id;
kpeter@773
    68
      Arc(int _id) : id(_id) {}
kpeter@773
    69
    public:
kpeter@773
    70
      Arc() { }
kpeter@773
    71
      Arc (Invalid) : id(-1) {}
kpeter@773
    72
      bool operator==(const Arc& arc) const { return id == arc.id; }
kpeter@773
    73
      bool operator!=(const Arc& arc) const { return id != arc.id; }
kpeter@773
    74
      bool operator<(const Arc& arc) const { return id < arc.id; }
kpeter@773
    75
    };
kpeter@773
    76
kpeter@773
    77
    Node source(const Arc& e) const { return Node(arc_source[e.id]); }
kpeter@773
    78
    Node target(const Arc& e) const { return Node(arc_target[e.id]); }
kpeter@773
    79
kpeter@773
    80
    void first(Node& n) const { n.id = node_num - 1; }
kpeter@773
    81
    static void next(Node& n) { --n.id; }
kpeter@773
    82
kpeter@773
    83
    void first(Arc& e) const { e.id = arc_num - 1; }
kpeter@773
    84
    static void next(Arc& e) { --e.id; }
kpeter@773
    85
alpar@877
    86
    void firstOut(Arc& e, const Node& n) const {
alpar@877
    87
      e.id = node_first_out[n.id] != node_first_out[n.id + 1] ?
kpeter@773
    88
        node_first_out[n.id] : -1;
kpeter@773
    89
    }
kpeter@773
    90
    void nextOut(Arc& e) const { e.id = arc_next_out[e.id]; }
kpeter@773
    91
kpeter@773
    92
    void firstIn(Arc& e, const Node& n) const { e.id = node_first_in[n.id]; }
kpeter@773
    93
    void nextIn(Arc& e) const { e.id = arc_next_in[e.id]; }
kpeter@773
    94
kpeter@778
    95
    static int id(const Node& n) { return n.id; }
kpeter@778
    96
    static Node nodeFromId(int id) { return Node(id); }
kpeter@773
    97
    int maxNodeId() const { return node_num - 1; }
kpeter@773
    98
kpeter@778
    99
    static int id(const Arc& e) { return e.id; }
kpeter@778
   100
    static Arc arcFromId(int id) { return Arc(id); }
kpeter@773
   101
    int maxArcId() const { return arc_num - 1; }
kpeter@773
   102
kpeter@773
   103
    typedef True NodeNumTag;
kpeter@773
   104
    typedef True ArcNumTag;
kpeter@773
   105
kpeter@773
   106
    int nodeNum() const { return node_num; }
kpeter@773
   107
    int arcNum() const { return arc_num; }
kpeter@773
   108
kpeter@773
   109
  private:
kpeter@773
   110
kpeter@773
   111
    template <typename Digraph, typename NodeRefMap>
kpeter@773
   112
    class ArcLess {
kpeter@773
   113
    public:
kpeter@773
   114
      typedef typename Digraph::Arc Arc;
kpeter@773
   115
alpar@877
   116
      ArcLess(const Digraph &_graph, const NodeRefMap& _nodeRef)
kpeter@773
   117
        : digraph(_graph), nodeRef(_nodeRef) {}
alpar@877
   118
kpeter@773
   119
      bool operator()(const Arc& left, const Arc& right) const {
alpar@877
   120
        return nodeRef[digraph.target(left)] < nodeRef[digraph.target(right)];
kpeter@773
   121
      }
kpeter@773
   122
    private:
kpeter@773
   123
      const Digraph& digraph;
kpeter@773
   124
      const NodeRefMap& nodeRef;
kpeter@773
   125
    };
alpar@877
   126
kpeter@773
   127
  public:
kpeter@773
   128
kpeter@773
   129
    typedef True BuildTag;
alpar@877
   130
kpeter@774
   131
    void clear() {
kpeter@774
   132
      if (built) {
kpeter@773
   133
        delete[] node_first_out;
kpeter@773
   134
        delete[] node_first_in;
kpeter@773
   135
        delete[] arc_source;
kpeter@773
   136
        delete[] arc_target;
kpeter@773
   137
        delete[] arc_next_out;
kpeter@773
   138
        delete[] arc_next_in;
kpeter@773
   139
      }
kpeter@774
   140
      built = false;
kpeter@774
   141
      node_num = 0;
kpeter@774
   142
      arc_num = 0;
kpeter@774
   143
    }
alpar@877
   144
kpeter@774
   145
    template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
kpeter@774
   146
    void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
kpeter@773
   147
      typedef typename Digraph::Node GNode;
kpeter@773
   148
      typedef typename Digraph::Arc GArc;
kpeter@773
   149
kpeter@774
   150
      built = true;
kpeter@774
   151
kpeter@773
   152
      node_num = countNodes(digraph);
kpeter@773
   153
      arc_num = countArcs(digraph);
kpeter@773
   154
kpeter@773
   155
      node_first_out = new int[node_num + 1];
kpeter@773
   156
      node_first_in = new int[node_num];
kpeter@773
   157
kpeter@773
   158
      arc_source = new int[arc_num];
kpeter@773
   159
      arc_target = new int[arc_num];
kpeter@773
   160
      arc_next_out = new int[arc_num];
kpeter@773
   161
      arc_next_in = new int[arc_num];
kpeter@773
   162
kpeter@773
   163
      int node_index = 0;
kpeter@773
   164
      for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
kpeter@773
   165
        nodeRef[n] = Node(node_index);
kpeter@773
   166
        node_first_in[node_index] = -1;
kpeter@773
   167
        ++node_index;
kpeter@773
   168
      }
kpeter@773
   169
kpeter@773
   170
      ArcLess<Digraph, NodeRefMap> arcLess(digraph, nodeRef);
kpeter@773
   171
kpeter@773
   172
      int arc_index = 0;
kpeter@773
   173
      for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
kpeter@773
   174
        int source = nodeRef[n].id;
kpeter@773
   175
        std::vector<GArc> arcs;
kpeter@773
   176
        for (typename Digraph::OutArcIt e(digraph, n); e != INVALID; ++e) {
kpeter@773
   177
          arcs.push_back(e);
kpeter@773
   178
        }
kpeter@773
   179
        if (!arcs.empty()) {
kpeter@773
   180
          node_first_out[source] = arc_index;
kpeter@773
   181
          std::sort(arcs.begin(), arcs.end(), arcLess);
kpeter@773
   182
          for (typename std::vector<GArc>::iterator it = arcs.begin();
kpeter@773
   183
               it != arcs.end(); ++it) {
kpeter@773
   184
            int target = nodeRef[digraph.target(*it)].id;
kpeter@773
   185
            arcRef[*it] = Arc(arc_index);
alpar@877
   186
            arc_source[arc_index] = source;
kpeter@773
   187
            arc_target[arc_index] = target;
kpeter@773
   188
            arc_next_in[arc_index] = node_first_in[target];
kpeter@773
   189
            node_first_in[target] = arc_index;
kpeter@773
   190
            arc_next_out[arc_index] = arc_index + 1;
kpeter@773
   191
            ++arc_index;
kpeter@773
   192
          }
kpeter@773
   193
          arc_next_out[arc_index - 1] = -1;
kpeter@773
   194
        } else {
kpeter@773
   195
          node_first_out[source] = arc_index;
kpeter@773
   196
        }
kpeter@773
   197
      }
kpeter@773
   198
      node_first_out[node_num] = arc_num;
kpeter@773
   199
    }
alpar@877
   200
kpeter@777
   201
    template <typename ArcListIterator>
kpeter@777
   202
    void build(int n, ArcListIterator first, ArcListIterator last) {
kpeter@777
   203
      built = true;
kpeter@777
   204
kpeter@777
   205
      node_num = n;
kpeter@777
   206
      arc_num = std::distance(first, last);
kpeter@777
   207
kpeter@777
   208
      node_first_out = new int[node_num + 1];
kpeter@777
   209
      node_first_in = new int[node_num];
kpeter@777
   210
kpeter@777
   211
      arc_source = new int[arc_num];
kpeter@777
   212
      arc_target = new int[arc_num];
kpeter@777
   213
      arc_next_out = new int[arc_num];
kpeter@777
   214
      arc_next_in = new int[arc_num];
alpar@877
   215
kpeter@777
   216
      for (int i = 0; i != node_num; ++i) {
kpeter@777
   217
        node_first_in[i] = -1;
alpar@877
   218
      }
alpar@877
   219
kpeter@777
   220
      int arc_index = 0;
kpeter@777
   221
      for (int i = 0; i != node_num; ++i) {
kpeter@777
   222
        node_first_out[i] = arc_index;
kpeter@777
   223
        for ( ; first != last && (*first).first == i; ++first) {
kpeter@777
   224
          int j = (*first).second;
kpeter@777
   225
          LEMON_ASSERT(j >= 0 && j < node_num,
kpeter@777
   226
            "Wrong arc list for StaticDigraph::build()");
kpeter@777
   227
          arc_source[arc_index] = i;
kpeter@777
   228
          arc_target[arc_index] = j;
kpeter@777
   229
          arc_next_in[arc_index] = node_first_in[j];
kpeter@777
   230
          node_first_in[j] = arc_index;
kpeter@777
   231
          arc_next_out[arc_index] = arc_index + 1;
kpeter@777
   232
          ++arc_index;
kpeter@777
   233
        }
kpeter@777
   234
        if (arc_index > node_first_out[i])
kpeter@777
   235
          arc_next_out[arc_index - 1] = -1;
kpeter@777
   236
      }
kpeter@777
   237
      LEMON_ASSERT(first == last,
kpeter@777
   238
        "Wrong arc list for StaticDigraph::build()");
kpeter@777
   239
      node_first_out[node_num] = arc_num;
kpeter@777
   240
    }
kpeter@773
   241
kpeter@773
   242
  protected:
kpeter@773
   243
kpeter@773
   244
    void fastFirstOut(Arc& e, const Node& n) const {
kpeter@773
   245
      e.id = node_first_out[n.id];
kpeter@773
   246
    }
kpeter@773
   247
kpeter@773
   248
    static void fastNextOut(Arc& e) {
kpeter@773
   249
      ++e.id;
kpeter@773
   250
    }
kpeter@773
   251
    void fastLastOut(Arc& e, const Node& n) const {
kpeter@773
   252
      e.id = node_first_out[n.id + 1];
kpeter@773
   253
    }
kpeter@773
   254
kpeter@774
   255
  protected:
kpeter@774
   256
    bool built;
kpeter@773
   257
    int node_num;
kpeter@773
   258
    int arc_num;
kpeter@773
   259
    int *node_first_out;
kpeter@773
   260
    int *node_first_in;
kpeter@773
   261
    int *arc_source;
kpeter@773
   262
    int *arc_target;
kpeter@773
   263
    int *arc_next_in;
kpeter@773
   264
    int *arc_next_out;
kpeter@773
   265
  };
kpeter@773
   266
kpeter@773
   267
  typedef DigraphExtender<StaticDigraphBase> ExtendedStaticDigraphBase;
kpeter@773
   268
kpeter@773
   269
kpeter@775
   270
  /// \ingroup graphs
kpeter@775
   271
  ///
kpeter@775
   272
  /// \brief A static directed graph class.
kpeter@775
   273
  ///
kpeter@775
   274
  /// \ref StaticDigraph is a highly efficient digraph implementation,
kpeter@775
   275
  /// but it is fully static.
kpeter@775
   276
  /// It stores only two \c int values for each node and only four \c int
kpeter@775
   277
  /// values for each arc. Moreover it provides faster item iteration than
kpeter@775
   278
  /// \ref ListDigraph and \ref SmartDigraph, especially using \c OutArcIt
kpeter@775
   279
  /// iterators, since its arcs are stored in an appropriate order.
kpeter@775
   280
  /// However it only provides build() and clear() functions and does not
kpeter@775
   281
  /// support any other modification of the digraph.
kpeter@775
   282
  ///
kpeter@776
   283
  /// Since this digraph structure is completely static, its nodes and arcs
kpeter@776
   284
  /// can be indexed with integers from the ranges <tt>[0..nodeNum()-1]</tt>
alpar@877
   285
  /// and <tt>[0..arcNum()-1]</tt>, respectively.
kpeter@776
   286
  /// The index of an item is the same as its ID, it can be obtained
kpeter@776
   287
  /// using the corresponding \ref index() or \ref concepts::Digraph::id()
kpeter@776
   288
  /// "id()" function. A node or arc with a certain index can be obtained
kpeter@776
   289
  /// using node() or arc().
kpeter@776
   290
  ///
kpeter@775
   291
  /// This type fully conforms to the \ref concepts::Digraph "Digraph concept".
kpeter@775
   292
  /// Most of its member functions and nested classes are documented
kpeter@775
   293
  /// only in the concept class.
kpeter@775
   294
  ///
kpeter@787
   295
  /// This class provides constant time counting for nodes and arcs.
kpeter@787
   296
  ///
kpeter@775
   297
  /// \sa concepts::Digraph
kpeter@773
   298
  class StaticDigraph : public ExtendedStaticDigraphBase {
kpeter@773
   299
  public:
kpeter@773
   300
kpeter@773
   301
    typedef ExtendedStaticDigraphBase Parent;
alpar@877
   302
kpeter@774
   303
  public:
alpar@877
   304
kpeter@776
   305
    /// \brief Constructor
kpeter@775
   306
    ///
kpeter@776
   307
    /// Default constructor.
kpeter@776
   308
    StaticDigraph() : Parent() {}
kpeter@776
   309
kpeter@776
   310
    /// \brief The node with the given index.
kpeter@776
   311
    ///
kpeter@776
   312
    /// This function returns the node with the given index.
kpeter@776
   313
    /// \sa index()
kpeter@778
   314
    static Node node(int ix) { return Parent::nodeFromId(ix); }
kpeter@776
   315
kpeter@776
   316
    /// \brief The arc with the given index.
kpeter@776
   317
    ///
kpeter@776
   318
    /// This function returns the arc with the given index.
kpeter@776
   319
    /// \sa index()
kpeter@778
   320
    static Arc arc(int ix) { return Parent::arcFromId(ix); }
kpeter@776
   321
kpeter@776
   322
    /// \brief The index of the given node.
kpeter@776
   323
    ///
kpeter@776
   324
    /// This function returns the index of the the given node.
kpeter@776
   325
    /// \sa node()
kpeter@778
   326
    static int index(Node node) { return Parent::id(node); }
kpeter@776
   327
kpeter@776
   328
    /// \brief The index of the given arc.
kpeter@776
   329
    ///
kpeter@776
   330
    /// This function returns the index of the the given arc.
kpeter@776
   331
    /// \sa arc()
kpeter@778
   332
    static int index(Arc arc) { return Parent::id(arc); }
kpeter@776
   333
kpeter@776
   334
    /// \brief Number of nodes.
kpeter@776
   335
    ///
kpeter@776
   336
    /// This function returns the number of nodes.
kpeter@776
   337
    int nodeNum() const { return node_num; }
kpeter@776
   338
kpeter@776
   339
    /// \brief Number of arcs.
kpeter@776
   340
    ///
kpeter@776
   341
    /// This function returns the number of arcs.
kpeter@776
   342
    int arcNum() const { return arc_num; }
kpeter@776
   343
kpeter@775
   344
    /// \brief Build the digraph copying another digraph.
kpeter@775
   345
    ///
kpeter@775
   346
    /// This function builds the digraph copying another digraph of any
kpeter@775
   347
    /// kind. It can be called more than once, but in such case, the whole
kpeter@775
   348
    /// structure and all maps will be cleared and rebuilt.
kpeter@775
   349
    ///
kpeter@775
   350
    /// This method also makes possible to copy a digraph to a StaticDigraph
kpeter@775
   351
    /// structure using \ref DigraphCopy.
alpar@877
   352
    ///
kpeter@775
   353
    /// \param digraph An existing digraph to be copied.
kpeter@775
   354
    /// \param nodeRef The node references will be copied into this map.
kpeter@775
   355
    /// Its key type must be \c Digraph::Node and its value type must be
kpeter@775
   356
    /// \c StaticDigraph::Node.
kpeter@775
   357
    /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
kpeter@775
   358
    /// concept.
kpeter@775
   359
    /// \param arcRef The arc references will be copied into this map.
kpeter@775
   360
    /// Its key type must be \c Digraph::Arc and its value type must be
kpeter@775
   361
    /// \c StaticDigraph::Arc.
kpeter@775
   362
    /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
kpeter@775
   363
    ///
kpeter@775
   364
    /// \note If you do not need the arc references, then you could use
kpeter@775
   365
    /// \ref NullMap for the last parameter. However the node references
kpeter@775
   366
    /// are required by the function itself, thus they must be readable
kpeter@775
   367
    /// from the map.
kpeter@774
   368
    template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
kpeter@774
   369
    void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
kpeter@774
   370
      if (built) Parent::clear();
kpeter@774
   371
      Parent::build(digraph, nodeRef, arcRef);
kpeter@774
   372
    }
alpar@877
   373
kpeter@777
   374
    /// \brief Build the digraph from an arc list.
kpeter@777
   375
    ///
kpeter@777
   376
    /// This function builds the digraph from the given arc list.
kpeter@777
   377
    /// It can be called more than once, but in such case, the whole
kpeter@777
   378
    /// structure and all maps will be cleared and rebuilt.
kpeter@777
   379
    ///
kpeter@777
   380
    /// The list of the arcs must be given in the range <tt>[begin, end)</tt>
kpeter@777
   381
    /// specified by STL compatible itartors whose \c value_type must be
kpeter@777
   382
    /// <tt>std::pair<int,int></tt>.
kpeter@777
   383
    /// Each arc must be specified by a pair of integer indices
kpeter@777
   384
    /// from the range <tt>[0..n-1]</tt>. <i>The pairs must be in a
kpeter@777
   385
    /// non-decreasing order with respect to their first values.</i>
kpeter@777
   386
    /// If the k-th pair in the list is <tt>(i,j)</tt>, then
kpeter@777
   387
    /// <tt>arc(k-1)</tt> will connect <tt>node(i)</tt> to <tt>node(j)</tt>.
kpeter@777
   388
    ///
kpeter@777
   389
    /// \param n The number of nodes.
kpeter@777
   390
    /// \param begin An iterator pointing to the beginning of the arc list.
kpeter@777
   391
    /// \param end An iterator pointing to the end of the arc list.
kpeter@777
   392
    ///
kpeter@777
   393
    /// For example, a simple digraph can be constructed like this.
kpeter@777
   394
    /// \code
kpeter@777
   395
    ///   std::vector<std::pair<int,int> > arcs;
kpeter@777
   396
    ///   arcs.push_back(std::make_pair(0,1));
kpeter@777
   397
    ///   arcs.push_back(std::make_pair(0,2));
kpeter@777
   398
    ///   arcs.push_back(std::make_pair(1,3));
kpeter@777
   399
    ///   arcs.push_back(std::make_pair(1,2));
kpeter@777
   400
    ///   arcs.push_back(std::make_pair(3,0));
kpeter@777
   401
    ///   StaticDigraph gr;
kpeter@777
   402
    ///   gr.build(4, arcs.begin(), arcs.end());
kpeter@777
   403
    /// \endcode
kpeter@777
   404
    template <typename ArcListIterator>
kpeter@777
   405
    void build(int n, ArcListIterator begin, ArcListIterator end) {
kpeter@777
   406
      if (built) Parent::clear();
kpeter@777
   407
      StaticDigraphBase::build(n, begin, end);
kpeter@777
   408
      notifier(Node()).build();
kpeter@777
   409
      notifier(Arc()).build();
kpeter@777
   410
    }
kpeter@777
   411
kpeter@776
   412
    /// \brief Clear the digraph.
kpeter@776
   413
    ///
kpeter@776
   414
    /// This function erases all nodes and arcs from the digraph.
kpeter@776
   415
    void clear() {
kpeter@776
   416
      Parent::clear();
kpeter@776
   417
    }
kpeter@773
   418
kpeter@773
   419
  protected:
kpeter@773
   420
kpeter@773
   421
    using Parent::fastFirstOut;
kpeter@773
   422
    using Parent::fastNextOut;
kpeter@773
   423
    using Parent::fastLastOut;
alpar@877
   424
kpeter@773
   425
  public:
kpeter@773
   426
kpeter@773
   427
    class OutArcIt : public Arc {
kpeter@773
   428
    public:
kpeter@773
   429
kpeter@773
   430
      OutArcIt() { }
kpeter@773
   431
kpeter@773
   432
      OutArcIt(Invalid i) : Arc(i) { }
kpeter@773
   433
kpeter@773
   434
      OutArcIt(const StaticDigraph& digraph, const Node& node) {
alpar@877
   435
        digraph.fastFirstOut(*this, node);
alpar@877
   436
        digraph.fastLastOut(last, node);
kpeter@773
   437
        if (last == *this) *this = INVALID;
kpeter@773
   438
      }
kpeter@773
   439
kpeter@773
   440
      OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) {
kpeter@773
   441
        if (arc != INVALID) {
kpeter@773
   442
          digraph.fastLastOut(last, digraph.source(arc));
kpeter@773
   443
        }
kpeter@773
   444
      }
kpeter@773
   445
alpar@877
   446
      OutArcIt& operator++() {
kpeter@773
   447
        StaticDigraph::fastNextOut(*this);
kpeter@773
   448
        if (last == *this) *this = INVALID;
alpar@877
   449
        return *this;
kpeter@773
   450
      }
kpeter@773
   451
kpeter@773
   452
    private:
kpeter@773
   453
      Arc last;
kpeter@773
   454
    };
kpeter@773
   455
kpeter@774
   456
    Node baseNode(const OutArcIt &arc) const {
kpeter@774
   457
      return Parent::source(static_cast<const Arc&>(arc));
kpeter@774
   458
    }
kpeter@774
   459
kpeter@774
   460
    Node runningNode(const OutArcIt &arc) const {
kpeter@774
   461
      return Parent::target(static_cast<const Arc&>(arc));
kpeter@774
   462
    }
kpeter@774
   463
kpeter@774
   464
    Node baseNode(const InArcIt &arc) const {
kpeter@774
   465
      return Parent::target(static_cast<const Arc&>(arc));
kpeter@774
   466
    }
kpeter@774
   467
kpeter@774
   468
    Node runningNode(const InArcIt &arc) const {
kpeter@774
   469
      return Parent::source(static_cast<const Arc&>(arc));
kpeter@774
   470
    }
kpeter@774
   471
kpeter@773
   472
  };
kpeter@773
   473
kpeter@773
   474
}
kpeter@773
   475
kpeter@773
   476
#endif