lemon/list_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 604 8c3112a66878
parent 329 d900fd1e760f
child 559 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@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@39
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@39
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
alpar@39
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@39
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@39
     8
 *
alpar@39
     9
 * Permission to use, modify and distribute this software is granted
alpar@39
    10
 * provided that this copyright notice appears in all copies. For
alpar@39
    11
 * precise terms see the accompanying LICENSE file.
alpar@39
    12
 *
alpar@39
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@39
    14
 * express or implied, and with no claim as to its suitability for any
alpar@39
    15
 * purpose.
alpar@39
    16
 *
alpar@39
    17
 */
alpar@39
    18
deba@57
    19
#ifndef LEMON_LIST_GRAPH_H
deba@57
    20
#define LEMON_LIST_GRAPH_H
deba@57
    21
deba@57
    22
///\ingroup graphs
deba@57
    23
///\file
deba@57
    24
///\brief ListDigraph, ListGraph classes.
deba@57
    25
deba@220
    26
#include <lemon/core.h>
deba@220
    27
#include <lemon/error.h>
deba@57
    28
#include <lemon/bits/graph_extender.h>
deba@57
    29
deba@57
    30
#include <vector>
deba@57
    31
#include <list>
deba@57
    32
deba@57
    33
namespace lemon {
deba@57
    34
deba@57
    35
  class ListDigraphBase {
deba@57
    36
deba@57
    37
  protected:
deba@57
    38
    struct NodeT {
deba@57
    39
      int first_in, first_out;
deba@57
    40
      int prev, next;
deba@57
    41
    };
alpar@209
    42
deba@57
    43
    struct ArcT {
deba@57
    44
      int target, source;
deba@57
    45
      int prev_in, prev_out;
deba@57
    46
      int next_in, next_out;
deba@57
    47
    };
deba@57
    48
deba@57
    49
    std::vector<NodeT> nodes;
deba@57
    50
deba@57
    51
    int first_node;
deba@57
    52
deba@57
    53
    int first_free_node;
deba@57
    54
deba@57
    55
    std::vector<ArcT> arcs;
deba@57
    56
deba@57
    57
    int first_free_arc;
alpar@209
    58
deba@57
    59
  public:
alpar@209
    60
deba@57
    61
    typedef ListDigraphBase Digraph;
alpar@209
    62
deba@57
    63
    class Node {
deba@57
    64
      friend class ListDigraphBase;
deba@57
    65
    protected:
deba@57
    66
deba@57
    67
      int id;
deba@57
    68
      explicit Node(int pid) { id = pid;}
deba@57
    69
deba@57
    70
    public:
deba@57
    71
      Node() {}
deba@57
    72
      Node (Invalid) { id = -1; }
deba@57
    73
      bool operator==(const Node& node) const {return id == node.id;}
deba@57
    74
      bool operator!=(const Node& node) const {return id != node.id;}
deba@57
    75
      bool operator<(const Node& node) const {return id < node.id;}
deba@57
    76
    };
deba@57
    77
deba@57
    78
    class Arc {
deba@57
    79
      friend class ListDigraphBase;
deba@57
    80
    protected:
deba@57
    81
deba@57
    82
      int id;
deba@57
    83
      explicit Arc(int pid) { id = pid;}
deba@57
    84
deba@57
    85
    public:
deba@57
    86
      Arc() {}
deba@57
    87
      Arc (Invalid) { id = -1; }
deba@57
    88
      bool operator==(const Arc& arc) const {return id == arc.id;}
deba@57
    89
      bool operator!=(const Arc& arc) const {return id != arc.id;}
deba@57
    90
      bool operator<(const Arc& arc) const {return id < arc.id;}
deba@57
    91
    };
deba@57
    92
deba@57
    93
deba@57
    94
deba@57
    95
    ListDigraphBase()
deba@57
    96
      : nodes(), first_node(-1),
alpar@209
    97
        first_free_node(-1), arcs(), first_free_arc(-1) {}
deba@57
    98
alpar@209
    99
alpar@209
   100
    int maxNodeId() const { return nodes.size()-1; }
deba@57
   101
    int maxArcId() const { return arcs.size()-1; }
deba@57
   102
deba@57
   103
    Node source(Arc e) const { return Node(arcs[e.id].source); }
deba@57
   104
    Node target(Arc e) const { return Node(arcs[e.id].target); }
deba@57
   105
deba@57
   106
alpar@209
   107
    void first(Node& node) const {
deba@57
   108
      node.id = first_node;
deba@57
   109
    }
deba@57
   110
deba@57
   111
    void next(Node& node) const {
deba@57
   112
      node.id = nodes[node.id].next;
deba@57
   113
    }
deba@57
   114
deba@57
   115
alpar@209
   116
    void first(Arc& arc) const {
deba@57
   117
      int n;
alpar@209
   118
      for(n = first_node;
alpar@209
   119
          n!=-1 && nodes[n].first_in == -1;
alpar@209
   120
          n = nodes[n].next) {}
kpeter@73
   121
      arc.id = (n == -1) ? -1 : nodes[n].first_in;
deba@57
   122
    }
deba@57
   123
deba@57
   124
    void next(Arc& arc) const {
deba@57
   125
      if (arcs[arc.id].next_in != -1) {
alpar@209
   126
        arc.id = arcs[arc.id].next_in;
deba@57
   127
      } else {
alpar@209
   128
        int n;
alpar@209
   129
        for(n = nodes[arcs[arc.id].target].next;
alpar@209
   130
            n!=-1 && nodes[n].first_in == -1;
alpar@209
   131
            n = nodes[n].next) {}
alpar@209
   132
        arc.id = (n == -1) ? -1 : nodes[n].first_in;
alpar@209
   133
      }
deba@57
   134
    }
deba@57
   135
deba@57
   136
    void firstOut(Arc &e, const Node& v) const {
deba@57
   137
      e.id = nodes[v.id].first_out;
deba@57
   138
    }
deba@57
   139
    void nextOut(Arc &e) const {
deba@57
   140
      e.id=arcs[e.id].next_out;
deba@57
   141
    }
deba@57
   142
deba@57
   143
    void firstIn(Arc &e, const Node& v) const {
deba@57
   144
      e.id = nodes[v.id].first_in;
deba@57
   145
    }
deba@57
   146
    void nextIn(Arc &e) const {
deba@57
   147
      e.id=arcs[e.id].next_in;
deba@57
   148
    }
deba@57
   149
alpar@209
   150
deba@57
   151
    static int id(Node v) { return v.id; }
deba@57
   152
    static int id(Arc e) { return e.id; }
deba@57
   153
deba@57
   154
    static Node nodeFromId(int id) { return Node(id);}
deba@57
   155
    static Arc arcFromId(int id) { return Arc(id);}
deba@57
   156
alpar@209
   157
    bool valid(Node n) const {
alpar@209
   158
      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
alpar@209
   159
        nodes[n.id].prev != -2;
deba@149
   160
    }
deba@149
   161
alpar@209
   162
    bool valid(Arc a) const {
alpar@209
   163
      return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
alpar@209
   164
        arcs[a.id].prev_in != -2;
deba@149
   165
    }
deba@149
   166
alpar@209
   167
    Node addNode() {
deba@57
   168
      int n;
alpar@209
   169
deba@57
   170
      if(first_free_node==-1) {
alpar@209
   171
        n = nodes.size();
alpar@209
   172
        nodes.push_back(NodeT());
deba@57
   173
      } else {
alpar@209
   174
        n = first_free_node;
alpar@209
   175
        first_free_node = nodes[n].next;
deba@57
   176
      }
alpar@209
   177
deba@57
   178
      nodes[n].next = first_node;
deba@57
   179
      if(first_node != -1) nodes[first_node].prev = n;
deba@57
   180
      first_node = n;
deba@57
   181
      nodes[n].prev = -1;
alpar@209
   182
deba@57
   183
      nodes[n].first_in = nodes[n].first_out = -1;
alpar@209
   184
deba@57
   185
      return Node(n);
deba@57
   186
    }
alpar@209
   187
deba@57
   188
    Arc addArc(Node u, Node v) {
alpar@209
   189
      int n;
deba@57
   190
deba@57
   191
      if (first_free_arc == -1) {
alpar@209
   192
        n = arcs.size();
alpar@209
   193
        arcs.push_back(ArcT());
deba@57
   194
      } else {
alpar@209
   195
        n = first_free_arc;
alpar@209
   196
        first_free_arc = arcs[n].next_in;
deba@57
   197
      }
alpar@209
   198
alpar@209
   199
      arcs[n].source = u.id;
deba@57
   200
      arcs[n].target = v.id;
deba@57
   201
deba@57
   202
      arcs[n].next_out = nodes[u.id].first_out;
deba@57
   203
      if(nodes[u.id].first_out != -1) {
alpar@209
   204
        arcs[nodes[u.id].first_out].prev_out = n;
deba@57
   205
      }
alpar@209
   206
deba@57
   207
      arcs[n].next_in = nodes[v.id].first_in;
deba@57
   208
      if(nodes[v.id].first_in != -1) {
alpar@209
   209
        arcs[nodes[v.id].first_in].prev_in = n;
deba@57
   210
      }
alpar@209
   211
deba@57
   212
      arcs[n].prev_in = arcs[n].prev_out = -1;
alpar@209
   213
deba@57
   214
      nodes[u.id].first_out = nodes[v.id].first_in = n;
deba@57
   215
deba@57
   216
      return Arc(n);
deba@57
   217
    }
alpar@209
   218
deba@57
   219
    void erase(const Node& node) {
deba@57
   220
      int n = node.id;
alpar@209
   221
deba@57
   222
      if(nodes[n].next != -1) {
alpar@209
   223
        nodes[nodes[n].next].prev = nodes[n].prev;
deba@57
   224
      }
alpar@209
   225
deba@57
   226
      if(nodes[n].prev != -1) {
alpar@209
   227
        nodes[nodes[n].prev].next = nodes[n].next;
deba@57
   228
      } else {
alpar@209
   229
        first_node = nodes[n].next;
deba@57
   230
      }
alpar@209
   231
deba@57
   232
      nodes[n].next = first_free_node;
deba@57
   233
      first_free_node = n;
deba@149
   234
      nodes[n].prev = -2;
deba@57
   235
deba@57
   236
    }
alpar@209
   237
deba@57
   238
    void erase(const Arc& arc) {
deba@57
   239
      int n = arc.id;
alpar@209
   240
deba@57
   241
      if(arcs[n].next_in!=-1) {
alpar@209
   242
        arcs[arcs[n].next_in].prev_in = arcs[n].prev_in;
deba@57
   243
      }
deba@57
   244
deba@57
   245
      if(arcs[n].prev_in!=-1) {
alpar@209
   246
        arcs[arcs[n].prev_in].next_in = arcs[n].next_in;
deba@57
   247
      } else {
alpar@209
   248
        nodes[arcs[n].target].first_in = arcs[n].next_in;
deba@57
   249
      }
deba@57
   250
alpar@209
   251
deba@57
   252
      if(arcs[n].next_out!=-1) {
alpar@209
   253
        arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
alpar@209
   254
      }
deba@57
   255
deba@57
   256
      if(arcs[n].prev_out!=-1) {
alpar@209
   257
        arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
deba@57
   258
      } else {
alpar@209
   259
        nodes[arcs[n].source].first_out = arcs[n].next_out;
deba@57
   260
      }
alpar@209
   261
deba@57
   262
      arcs[n].next_in = first_free_arc;
deba@149
   263
      first_free_arc = n;
deba@149
   264
      arcs[n].prev_in = -2;
deba@57
   265
    }
deba@57
   266
deba@57
   267
    void clear() {
deba@57
   268
      arcs.clear();
deba@57
   269
      nodes.clear();
deba@57
   270
      first_node = first_free_node = first_free_arc = -1;
deba@57
   271
    }
deba@57
   272
deba@57
   273
  protected:
alpar@209
   274
    void changeTarget(Arc e, Node n)
deba@57
   275
    {
deba@57
   276
      if(arcs[e.id].next_in != -1)
alpar@209
   277
        arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in;
deba@57
   278
      if(arcs[e.id].prev_in != -1)
alpar@209
   279
        arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in;
deba@57
   280
      else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in;
deba@57
   281
      if (nodes[n.id].first_in != -1) {
alpar@209
   282
        arcs[nodes[n.id].first_in].prev_in = e.id;
deba@57
   283
      }
deba@57
   284
      arcs[e.id].target = n.id;
deba@57
   285
      arcs[e.id].prev_in = -1;
deba@57
   286
      arcs[e.id].next_in = nodes[n.id].first_in;
deba@57
   287
      nodes[n.id].first_in = e.id;
deba@57
   288
    }
alpar@209
   289
    void changeSource(Arc e, Node n)
deba@57
   290
    {
deba@57
   291
      if(arcs[e.id].next_out != -1)
alpar@209
   292
        arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out;
deba@57
   293
      if(arcs[e.id].prev_out != -1)
alpar@209
   294
        arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out;
deba@57
   295
      else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out;
deba@57
   296
      if (nodes[n.id].first_out != -1) {
alpar@209
   297
        arcs[nodes[n.id].first_out].prev_out = e.id;
deba@57
   298
      }
deba@57
   299
      arcs[e.id].source = n.id;
deba@57
   300
      arcs[e.id].prev_out = -1;
deba@57
   301
      arcs[e.id].next_out = nodes[n.id].first_out;
deba@57
   302
      nodes[n.id].first_out = e.id;
deba@57
   303
    }
deba@57
   304
deba@57
   305
  };
deba@57
   306
deba@57
   307
  typedef DigraphExtender<ListDigraphBase> ExtendedListDigraphBase;
deba@57
   308
kpeter@73
   309
  /// \addtogroup graphs
deba@57
   310
  /// @{
deba@57
   311
alpar@209
   312
  ///A general directed graph structure.
deba@57
   313
alpar@209
   314
  ///\ref ListDigraph is a simple and fast <em>directed graph</em>
alpar@209
   315
  ///implementation based on static linked lists that are stored in
alpar@209
   316
  ///\c std::vector structures.
deba@57
   317
  ///
deba@57
   318
  ///It conforms to the \ref concepts::Digraph "Digraph concept" and it
kpeter@73
   319
  ///also provides several useful additional functionalities.
kpeter@73
   320
  ///Most of the member functions and nested classes are documented
kpeter@73
   321
  ///only in the concept class.
deba@57
   322
  ///
deba@57
   323
  ///An important extra feature of this digraph implementation is that
deba@57
   324
  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
deba@57
   325
  ///
kpeter@73
   326
  ///\sa concepts::Digraph
deba@57
   327
deba@57
   328
  class ListDigraph : public ExtendedListDigraphBase {
deba@57
   329
  private:
kpeter@73
   330
    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
alpar@209
   331
kpeter@73
   332
    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
deba@57
   333
    ///
deba@57
   334
    ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
deba@57
   335
    ///\brief Assignment of ListDigraph to another one is \e not allowed.
kpeter@73
   336
    ///Use copyDigraph() instead.
deba@57
   337
deba@57
   338
    ///Assignment of ListDigraph to another one is \e not allowed.
kpeter@73
   339
    ///Use copyDigraph() instead.
deba@57
   340
    void operator=(const ListDigraph &) {}
deba@57
   341
  public:
deba@57
   342
deba@57
   343
    typedef ExtendedListDigraphBase Parent;
deba@57
   344
deba@57
   345
    /// Constructor
alpar@209
   346
deba@57
   347
    /// Constructor.
deba@57
   348
    ///
deba@57
   349
    ListDigraph() {}
deba@57
   350
deba@57
   351
    ///Add a new node to the digraph.
alpar@209
   352
kpeter@73
   353
    ///Add a new node to the digraph.
kpeter@73
   354
    ///\return the new node.
deba@57
   355
    Node addNode() { return Parent::addNode(); }
deba@57
   356
deba@57
   357
    ///Add a new arc to the digraph.
alpar@209
   358
deba@57
   359
    ///Add a new arc to the digraph with source node \c s
deba@57
   360
    ///and target node \c t.
deba@57
   361
    ///\return the new arc.
alpar@209
   362
    Arc addArc(const Node& s, const Node& t) {
alpar@209
   363
      return Parent::addArc(s, t);
deba@57
   364
    }
deba@57
   365
deba@234
   366
    ///\brief Erase a node from the digraph.
deba@234
   367
    ///
deba@234
   368
    ///Erase a node from the digraph.
deba@234
   369
    ///
deba@234
   370
    void erase(const Node& n) { Parent::erase(n); }
deba@234
   371
deba@234
   372
    ///\brief Erase an arc from the digraph.
deba@234
   373
    ///
deba@234
   374
    ///Erase an arc from the digraph.
deba@234
   375
    ///
deba@234
   376
    void erase(const Arc& a) { Parent::erase(a); }
deba@234
   377
deba@149
   378
    /// Node validity check
deba@149
   379
deba@149
   380
    /// This function gives back true if the given node is valid,
alpar@209
   381
    /// ie. it is a real node of the graph.
deba@149
   382
    ///
deba@149
   383
    /// \warning A Node pointing to a removed item
deba@149
   384
    /// could become valid again later if new nodes are
deba@149
   385
    /// added to the graph.
deba@149
   386
    bool valid(Node n) const { return Parent::valid(n); }
deba@149
   387
deba@149
   388
    /// Arc validity check
deba@149
   389
deba@149
   390
    /// This function gives back true if the given arc is valid,
alpar@209
   391
    /// ie. it is a real arc of the graph.
deba@149
   392
    ///
deba@149
   393
    /// \warning An Arc pointing to a removed item
deba@149
   394
    /// could become valid again later if new nodes are
deba@149
   395
    /// added to the graph.
deba@149
   396
    bool valid(Arc a) const { return Parent::valid(a); }
deba@149
   397
deba@235
   398
    /// Change the target of \c a to \c n
deba@57
   399
deba@235
   400
    /// Change the target of \c a to \c n
deba@57
   401
    ///
deba@57
   402
    ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s referencing
deba@57
   403
    ///the changed arc remain valid. However <tt>InArcIt</tt>s are
deba@57
   404
    ///invalidated.
kpeter@73
   405
    ///
deba@57
   406
    ///\warning This functionality cannot be used together with the Snapshot
deba@57
   407
    ///feature.
deba@235
   408
    void changeTarget(Arc a, Node n) {
deba@235
   409
      Parent::changeTarget(a,n);
deba@57
   410
    }
deba@235
   411
    /// Change the source of \c a to \c n
deba@57
   412
deba@235
   413
    /// Change the source of \c a to \c n
deba@57
   414
    ///
deba@235
   415
    ///\note The <tt>InArcIt</tt>s referencing the changed arc remain
kpeter@313
   416
    ///valid. However the <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s are
deba@57
   417
    ///invalidated.
kpeter@73
   418
    ///
deba@57
   419
    ///\warning This functionality cannot be used together with the Snapshot
deba@57
   420
    ///feature.
deba@235
   421
    void changeSource(Arc a, Node n) {
deba@235
   422
      Parent::changeSource(a,n);
deba@57
   423
    }
deba@57
   424
deba@57
   425
    /// Invert the direction of an arc.
deba@57
   426
deba@57
   427
    ///\note The <tt>ArcIt</tt>s referencing the changed arc remain
deba@57
   428
    ///valid. However <tt>OutArcIt</tt>s and <tt>InArcIt</tt>s are
deba@57
   429
    ///invalidated.
kpeter@73
   430
    ///
deba@57
   431
    ///\warning This functionality cannot be used together with the Snapshot
deba@57
   432
    ///feature.
deba@57
   433
    void reverseArc(Arc e) {
deba@57
   434
      Node t=target(e);
deba@57
   435
      changeTarget(e,source(e));
deba@57
   436
      changeSource(e,t);
deba@57
   437
    }
deba@57
   438
kpeter@73
   439
    /// Reserve memory for nodes.
kpeter@73
   440
kpeter@73
   441
    /// Using this function it is possible to avoid the superfluous memory
deba@57
   442
    /// allocation: if you know that the digraph you want to build will
deba@57
   443
    /// be very large (e.g. it will contain millions of nodes and/or arcs)
deba@57
   444
    /// then it is worth reserving space for this amount before starting
deba@57
   445
    /// to build the digraph.
deba@57
   446
    /// \sa reserveArc
deba@57
   447
    void reserveNode(int n) { nodes.reserve(n); };
deba@57
   448
kpeter@73
   449
    /// Reserve memory for arcs.
deba@57
   450
kpeter@73
   451
    /// Using this function it is possible to avoid the superfluous memory
deba@57
   452
    /// allocation: if you know that the digraph you want to build will
deba@57
   453
    /// be very large (e.g. it will contain millions of nodes and/or arcs)
deba@57
   454
    /// then it is worth reserving space for this amount before starting
deba@57
   455
    /// to build the digraph.
deba@57
   456
    /// \sa reserveNode
deba@57
   457
    void reserveArc(int m) { arcs.reserve(m); };
deba@57
   458
deba@57
   459
    ///Contract two nodes.
deba@57
   460
deba@57
   461
    ///This function contracts two nodes.
deba@57
   462
    ///Node \p b will be removed but instead of deleting
deba@57
   463
    ///incident arcs, they will be joined to \p a.
deba@57
   464
    ///The last parameter \p r controls whether to remove loops. \c true
deba@57
   465
    ///means that loops will be removed.
deba@57
   466
    ///
kpeter@73
   467
    ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
deba@57
   468
    ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s
deba@57
   469
    ///may be invalidated.
kpeter@73
   470
    ///
deba@57
   471
    ///\warning This functionality cannot be used together with the Snapshot
deba@57
   472
    ///feature.
alpar@209
   473
    void contract(Node a, Node b, bool r = true)
deba@57
   474
    {
deba@57
   475
      for(OutArcIt e(*this,b);e!=INVALID;) {
alpar@209
   476
        OutArcIt f=e;
alpar@209
   477
        ++f;
alpar@209
   478
        if(r && target(e)==a) erase(e);
alpar@209
   479
        else changeSource(e,a);
alpar@209
   480
        e=f;
deba@57
   481
      }
deba@57
   482
      for(InArcIt e(*this,b);e!=INVALID;) {
alpar@209
   483
        InArcIt f=e;
alpar@209
   484
        ++f;
alpar@209
   485
        if(r && source(e)==a) erase(e);
alpar@209
   486
        else changeTarget(e,a);
alpar@209
   487
        e=f;
deba@57
   488
      }
deba@57
   489
      erase(b);
deba@57
   490
    }
deba@57
   491
deba@57
   492
    ///Split a node.
deba@57
   493
deba@57
   494
    ///This function splits a node. First a new node is added to the digraph,
deba@57
   495
    ///then the source of each outgoing arc of \c n is moved to this new node.
deba@57
   496
    ///If \c connect is \c true (this is the default value), then a new arc
deba@57
   497
    ///from \c n to the newly created node is also added.
deba@57
   498
    ///\return The newly created node.
deba@57
   499
    ///
deba@57
   500
    ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
deba@57
   501
    ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s may
alpar@209
   502
    ///be invalidated.
deba@57
   503
    ///
alpar@280
   504
    ///\warning This functionality cannot be used in conjunction with the
kpeter@73
   505
    ///Snapshot feature.
deba@57
   506
    Node split(Node n, bool connect = true) {
deba@57
   507
      Node b = addNode();
deba@57
   508
      for(OutArcIt e(*this,n);e!=INVALID;) {
kpeter@212
   509
        OutArcIt f=e;
alpar@209
   510
        ++f;
alpar@209
   511
        changeSource(e,b);
alpar@209
   512
        e=f;
deba@57
   513
      }
deba@57
   514
      if (connect) addArc(n,b);
deba@57
   515
      return b;
deba@57
   516
    }
alpar@209
   517
deba@57
   518
    ///Split an arc.
deba@57
   519
deba@57
   520
    ///This function splits an arc. First a new node \c b is added to
deba@57
   521
    ///the digraph, then the original arc is re-targeted to \c
deba@57
   522
    ///b. Finally an arc from \c b to the original target is added.
kpeter@73
   523
    ///
kpeter@73
   524
    ///\return The newly created node.
kpeter@73
   525
    ///
kpeter@73
   526
    ///\warning This functionality cannot be used together with the
kpeter@73
   527
    ///Snapshot feature.
deba@57
   528
    Node split(Arc e) {
deba@57
   529
      Node b = addNode();
deba@57
   530
      addArc(b,target(e));
deba@57
   531
      changeTarget(e,b);
deba@57
   532
      return b;
deba@57
   533
    }
alpar@209
   534
deba@57
   535
    /// \brief Class to make a snapshot of the digraph and restore
kpeter@73
   536
    /// it later.
deba@57
   537
    ///
kpeter@73
   538
    /// Class to make a snapshot of the digraph and restore it later.
deba@57
   539
    ///
deba@57
   540
    /// The newly added nodes and arcs can be removed using the
deba@57
   541
    /// restore() function.
deba@57
   542
    ///
kpeter@73
   543
    /// \warning Arc and node deletions and other modifications (e.g.
alpar@209
   544
    /// contracting, splitting, reversing arcs or nodes) cannot be
alpar@209
   545
    /// restored. These events invalidate the snapshot.
deba@57
   546
    class Snapshot {
deba@57
   547
    protected:
deba@57
   548
deba@57
   549
      typedef Parent::NodeNotifier NodeNotifier;
deba@57
   550
deba@57
   551
      class NodeObserverProxy : public NodeNotifier::ObserverBase {
deba@57
   552
      public:
deba@57
   553
deba@57
   554
        NodeObserverProxy(Snapshot& _snapshot)
deba@57
   555
          : snapshot(_snapshot) {}
deba@57
   556
deba@57
   557
        using NodeNotifier::ObserverBase::attach;
deba@57
   558
        using NodeNotifier::ObserverBase::detach;
deba@57
   559
        using NodeNotifier::ObserverBase::attached;
alpar@209
   560
deba@57
   561
      protected:
alpar@209
   562
deba@57
   563
        virtual void add(const Node& node) {
deba@57
   564
          snapshot.addNode(node);
deba@57
   565
        }
deba@57
   566
        virtual void add(const std::vector<Node>& nodes) {
deba@57
   567
          for (int i = nodes.size() - 1; i >= 0; ++i) {
deba@57
   568
            snapshot.addNode(nodes[i]);
deba@57
   569
          }
deba@57
   570
        }
deba@57
   571
        virtual void erase(const Node& node) {
deba@57
   572
          snapshot.eraseNode(node);
deba@57
   573
        }
deba@57
   574
        virtual void erase(const std::vector<Node>& nodes) {
deba@57
   575
          for (int i = 0; i < int(nodes.size()); ++i) {
deba@57
   576
            snapshot.eraseNode(nodes[i]);
deba@57
   577
          }
deba@57
   578
        }
deba@57
   579
        virtual void build() {
deba@57
   580
          Node node;
deba@57
   581
          std::vector<Node> nodes;
alpar@209
   582
          for (notifier()->first(node); node != INVALID;
deba@57
   583
               notifier()->next(node)) {
deba@57
   584
            nodes.push_back(node);
deba@57
   585
          }
deba@57
   586
          for (int i = nodes.size() - 1; i >= 0; --i) {
deba@57
   587
            snapshot.addNode(nodes[i]);
deba@57
   588
          }
deba@57
   589
        }
deba@57
   590
        virtual void clear() {
deba@57
   591
          Node node;
alpar@209
   592
          for (notifier()->first(node); node != INVALID;
deba@57
   593
               notifier()->next(node)) {
deba@57
   594
            snapshot.eraseNode(node);
deba@57
   595
          }
deba@57
   596
        }
deba@57
   597
deba@57
   598
        Snapshot& snapshot;
deba@57
   599
      };
deba@57
   600
deba@57
   601
      class ArcObserverProxy : public ArcNotifier::ObserverBase {
deba@57
   602
      public:
deba@57
   603
deba@57
   604
        ArcObserverProxy(Snapshot& _snapshot)
deba@57
   605
          : snapshot(_snapshot) {}
deba@57
   606
deba@57
   607
        using ArcNotifier::ObserverBase::attach;
deba@57
   608
        using ArcNotifier::ObserverBase::detach;
deba@57
   609
        using ArcNotifier::ObserverBase::attached;
alpar@209
   610
deba@57
   611
      protected:
deba@57
   612
deba@57
   613
        virtual void add(const Arc& arc) {
deba@57
   614
          snapshot.addArc(arc);
deba@57
   615
        }
deba@57
   616
        virtual void add(const std::vector<Arc>& arcs) {
deba@57
   617
          for (int i = arcs.size() - 1; i >= 0; ++i) {
deba@57
   618
            snapshot.addArc(arcs[i]);
deba@57
   619
          }
deba@57
   620
        }
deba@57
   621
        virtual void erase(const Arc& arc) {
deba@57
   622
          snapshot.eraseArc(arc);
deba@57
   623
        }
deba@57
   624
        virtual void erase(const std::vector<Arc>& arcs) {
deba@57
   625
          for (int i = 0; i < int(arcs.size()); ++i) {
deba@57
   626
            snapshot.eraseArc(arcs[i]);
deba@57
   627
          }
deba@57
   628
        }
deba@57
   629
        virtual void build() {
deba@57
   630
          Arc arc;
deba@57
   631
          std::vector<Arc> arcs;
alpar@209
   632
          for (notifier()->first(arc); arc != INVALID;
deba@57
   633
               notifier()->next(arc)) {
deba@57
   634
            arcs.push_back(arc);
deba@57
   635
          }
deba@57
   636
          for (int i = arcs.size() - 1; i >= 0; --i) {
deba@57
   637
            snapshot.addArc(arcs[i]);
deba@57
   638
          }
deba@57
   639
        }
deba@57
   640
        virtual void clear() {
deba@57
   641
          Arc arc;
alpar@209
   642
          for (notifier()->first(arc); arc != INVALID;
deba@57
   643
               notifier()->next(arc)) {
deba@57
   644
            snapshot.eraseArc(arc);
deba@57
   645
          }
deba@57
   646
        }
deba@57
   647
deba@57
   648
        Snapshot& snapshot;
deba@57
   649
      };
alpar@209
   650
deba@57
   651
      ListDigraph *digraph;
deba@57
   652
deba@57
   653
      NodeObserverProxy node_observer_proxy;
deba@57
   654
      ArcObserverProxy arc_observer_proxy;
deba@57
   655
deba@57
   656
      std::list<Node> added_nodes;
deba@57
   657
      std::list<Arc> added_arcs;
deba@57
   658
deba@57
   659
deba@57
   660
      void addNode(const Node& node) {
alpar@209
   661
        added_nodes.push_front(node);
deba@57
   662
      }
deba@57
   663
      void eraseNode(const Node& node) {
alpar@209
   664
        std::list<Node>::iterator it =
deba@57
   665
          std::find(added_nodes.begin(), added_nodes.end(), node);
deba@57
   666
        if (it == added_nodes.end()) {
deba@57
   667
          clear();
deba@57
   668
          arc_observer_proxy.detach();
deba@57
   669
          throw NodeNotifier::ImmediateDetach();
deba@57
   670
        } else {
deba@57
   671
          added_nodes.erase(it);
deba@57
   672
        }
deba@57
   673
      }
deba@57
   674
deba@57
   675
      void addArc(const Arc& arc) {
alpar@209
   676
        added_arcs.push_front(arc);
deba@57
   677
      }
deba@57
   678
      void eraseArc(const Arc& arc) {
alpar@209
   679
        std::list<Arc>::iterator it =
deba@57
   680
          std::find(added_arcs.begin(), added_arcs.end(), arc);
deba@57
   681
        if (it == added_arcs.end()) {
deba@57
   682
          clear();
alpar@209
   683
          node_observer_proxy.detach();
deba@57
   684
          throw ArcNotifier::ImmediateDetach();
deba@57
   685
        } else {
deba@57
   686
          added_arcs.erase(it);
alpar@209
   687
        }
deba@57
   688
      }
deba@57
   689
deba@57
   690
      void attach(ListDigraph &_digraph) {
alpar@209
   691
        digraph = &_digraph;
alpar@209
   692
        node_observer_proxy.attach(digraph->notifier(Node()));
deba@57
   693
        arc_observer_proxy.attach(digraph->notifier(Arc()));
deba@57
   694
      }
alpar@209
   695
deba@57
   696
      void detach() {
alpar@209
   697
        node_observer_proxy.detach();
alpar@209
   698
        arc_observer_proxy.detach();
deba@57
   699
      }
deba@57
   700
deba@57
   701
      bool attached() const {
deba@57
   702
        return node_observer_proxy.attached();
deba@57
   703
      }
deba@57
   704
deba@57
   705
      void clear() {
deba@57
   706
        added_nodes.clear();
alpar@209
   707
        added_arcs.clear();
deba@57
   708
      }
deba@57
   709
deba@57
   710
    public:
deba@57
   711
deba@57
   712
      /// \brief Default constructor.
deba@57
   713
      ///
deba@57
   714
      /// Default constructor.
deba@57
   715
      /// To actually make a snapshot you must call save().
alpar@209
   716
      Snapshot()
alpar@209
   717
        : digraph(0), node_observer_proxy(*this),
deba@57
   718
          arc_observer_proxy(*this) {}
alpar@209
   719
deba@57
   720
      /// \brief Constructor that immediately makes a snapshot.
alpar@209
   721
      ///
deba@57
   722
      /// This constructor immediately makes a snapshot of the digraph.
deba@57
   723
      /// \param _digraph The digraph we make a snapshot of.
alpar@209
   724
      Snapshot(ListDigraph &_digraph)
alpar@209
   725
        : node_observer_proxy(*this),
deba@57
   726
          arc_observer_proxy(*this) {
alpar@209
   727
        attach(_digraph);
deba@57
   728
      }
alpar@209
   729
deba@57
   730
      /// \brief Make a snapshot.
deba@57
   731
      ///
deba@57
   732
      /// Make a snapshot of the digraph.
deba@57
   733
      ///
deba@57
   734
      /// This function can be called more than once. In case of a repeated
deba@57
   735
      /// call, the previous snapshot gets lost.
deba@57
   736
      /// \param _digraph The digraph we make the snapshot of.
deba@57
   737
      void save(ListDigraph &_digraph) {
deba@57
   738
        if (attached()) {
deba@57
   739
          detach();
deba@57
   740
          clear();
deba@57
   741
        }
deba@57
   742
        attach(_digraph);
deba@57
   743
      }
alpar@209
   744
deba@57
   745
      /// \brief Undo the changes until the last snapshot.
alpar@209
   746
      //
deba@57
   747
      /// Undo the changes until the last snapshot created by save().
deba@57
   748
      void restore() {
alpar@209
   749
        detach();
alpar@209
   750
        for(std::list<Arc>::iterator it = added_arcs.begin();
deba@57
   751
            it != added_arcs.end(); ++it) {
alpar@209
   752
          digraph->erase(*it);
alpar@209
   753
        }
alpar@209
   754
        for(std::list<Node>::iterator it = added_nodes.begin();
deba@57
   755
            it != added_nodes.end(); ++it) {
alpar@209
   756
          digraph->erase(*it);
alpar@209
   757
        }
deba@57
   758
        clear();
deba@57
   759
      }
deba@57
   760
deba@57
   761
      /// \brief Gives back true when the snapshot is valid.
deba@57
   762
      ///
deba@57
   763
      /// Gives back true when the snapshot is valid.
deba@57
   764
      bool valid() const {
deba@57
   765
        return attached();
deba@57
   766
      }
deba@57
   767
    };
alpar@209
   768
deba@57
   769
  };
deba@57
   770
deba@57
   771
  ///@}
deba@57
   772
deba@57
   773
  class ListGraphBase {
deba@57
   774
deba@57
   775
  protected:
deba@57
   776
deba@57
   777
    struct NodeT {
deba@57
   778
      int first_out;
deba@57
   779
      int prev, next;
deba@57
   780
    };
alpar@209
   781
deba@57
   782
    struct ArcT {
deba@57
   783
      int target;
deba@57
   784
      int prev_out, next_out;
deba@57
   785
    };
deba@57
   786
deba@57
   787
    std::vector<NodeT> nodes;
deba@57
   788
deba@57
   789
    int first_node;
deba@57
   790
deba@57
   791
    int first_free_node;
deba@57
   792
deba@57
   793
    std::vector<ArcT> arcs;
deba@57
   794
deba@57
   795
    int first_free_arc;
alpar@209
   796
deba@57
   797
  public:
alpar@209
   798
deba@57
   799
    typedef ListGraphBase Digraph;
deba@57
   800
deba@57
   801
    class Node;
deba@57
   802
    class Arc;
deba@57
   803
    class Edge;
alpar@209
   804
deba@57
   805
    class Node {
deba@57
   806
      friend class ListGraphBase;
deba@57
   807
    protected:
deba@57
   808
deba@57
   809
      int id;
deba@57
   810
      explicit Node(int pid) { id = pid;}
deba@57
   811
deba@57
   812
    public:
deba@57
   813
      Node() {}
deba@57
   814
      Node (Invalid) { id = -1; }
deba@57
   815
      bool operator==(const Node& node) const {return id == node.id;}
deba@57
   816
      bool operator!=(const Node& node) const {return id != node.id;}
deba@57
   817
      bool operator<(const Node& node) const {return id < node.id;}
deba@57
   818
    };
deba@57
   819
deba@57
   820
    class Edge {
deba@57
   821
      friend class ListGraphBase;
deba@57
   822
    protected:
deba@57
   823
deba@57
   824
      int id;
deba@57
   825
      explicit Edge(int pid) { id = pid;}
deba@57
   826
deba@57
   827
    public:
deba@57
   828
      Edge() {}
deba@57
   829
      Edge (Invalid) { id = -1; }
kpeter@73
   830
      bool operator==(const Edge& edge) const {return id == edge.id;}
kpeter@73
   831
      bool operator!=(const Edge& edge) const {return id != edge.id;}
kpeter@73
   832
      bool operator<(const Edge& edge) const {return id < edge.id;}
deba@57
   833
    };
deba@57
   834
deba@57
   835
    class Arc {
deba@57
   836
      friend class ListGraphBase;
deba@57
   837
    protected:
deba@57
   838
deba@57
   839
      int id;
deba@57
   840
      explicit Arc(int pid) { id = pid;}
deba@57
   841
deba@57
   842
    public:
kpeter@329
   843
      operator Edge() const {
kpeter@329
   844
        return id != -1 ? edgeFromId(id / 2) : INVALID;
deba@238
   845
      }
deba@57
   846
deba@57
   847
      Arc() {}
deba@57
   848
      Arc (Invalid) { id = -1; }
deba@57
   849
      bool operator==(const Arc& arc) const {return id == arc.id;}
deba@57
   850
      bool operator!=(const Arc& arc) const {return id != arc.id;}
deba@57
   851
      bool operator<(const Arc& arc) const {return id < arc.id;}
deba@57
   852
    };
deba@57
   853
deba@57
   854
deba@57
   855
deba@57
   856
    ListGraphBase()
deba@57
   857
      : nodes(), first_node(-1),
alpar@209
   858
        first_free_node(-1), arcs(), first_free_arc(-1) {}
deba@57
   859
alpar@209
   860
alpar@209
   861
    int maxNodeId() const { return nodes.size()-1; }
deba@57
   862
    int maxEdgeId() const { return arcs.size() / 2 - 1; }
deba@57
   863
    int maxArcId() const { return arcs.size()-1; }
deba@57
   864
deba@57
   865
    Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
deba@57
   866
    Node target(Arc e) const { return Node(arcs[e.id].target); }
deba@57
   867
deba@57
   868
    Node u(Edge e) const { return Node(arcs[2 * e.id].target); }
deba@57
   869
    Node v(Edge e) const { return Node(arcs[2 * e.id + 1].target); }
deba@57
   870
deba@57
   871
    static bool direction(Arc e) {
deba@57
   872
      return (e.id & 1) == 1;
deba@57
   873
    }
deba@57
   874
deba@57
   875
    static Arc direct(Edge e, bool d) {
deba@57
   876
      return Arc(e.id * 2 + (d ? 1 : 0));
deba@57
   877
    }
deba@57
   878
alpar@209
   879
    void first(Node& node) const {
deba@57
   880
      node.id = first_node;
deba@57
   881
    }
deba@57
   882
deba@57
   883
    void next(Node& node) const {
deba@57
   884
      node.id = nodes[node.id].next;
deba@57
   885
    }
deba@57
   886
alpar@209
   887
    void first(Arc& e) const {
deba@57
   888
      int n = first_node;
deba@57
   889
      while (n != -1 && nodes[n].first_out == -1) {
deba@57
   890
        n = nodes[n].next;
deba@57
   891
      }
deba@57
   892
      e.id = (n == -1) ? -1 : nodes[n].first_out;
deba@57
   893
    }
deba@57
   894
deba@57
   895
    void next(Arc& e) const {
deba@57
   896
      if (arcs[e.id].next_out != -1) {
alpar@209
   897
        e.id = arcs[e.id].next_out;
deba@57
   898
      } else {
alpar@209
   899
        int n = nodes[arcs[e.id ^ 1].target].next;
deba@57
   900
        while(n != -1 && nodes[n].first_out == -1) {
deba@57
   901
          n = nodes[n].next;
deba@57
   902
        }
alpar@209
   903
        e.id = (n == -1) ? -1 : nodes[n].first_out;
alpar@209
   904
      }
deba@57
   905
    }
deba@57
   906
alpar@209
   907
    void first(Edge& e) const {
deba@57
   908
      int n = first_node;
deba@57
   909
      while (n != -1) {
deba@57
   910
        e.id = nodes[n].first_out;
deba@57
   911
        while ((e.id & 1) != 1) {
deba@57
   912
          e.id = arcs[e.id].next_out;
deba@57
   913
        }
deba@57
   914
        if (e.id != -1) {
deba@57
   915
          e.id /= 2;
deba@57
   916
          return;
alpar@209
   917
        }
deba@57
   918
        n = nodes[n].next;
deba@57
   919
      }
deba@57
   920
      e.id = -1;
deba@57
   921
    }
deba@57
   922
deba@57
   923
    void next(Edge& e) const {
deba@57
   924
      int n = arcs[e.id * 2].target;
deba@57
   925
      e.id = arcs[(e.id * 2) | 1].next_out;
deba@57
   926
      while ((e.id & 1) != 1) {
deba@57
   927
        e.id = arcs[e.id].next_out;
deba@57
   928
      }
deba@57
   929
      if (e.id != -1) {
deba@57
   930
        e.id /= 2;
deba@57
   931
        return;
alpar@209
   932
      }
deba@57
   933
      n = nodes[n].next;
deba@57
   934
      while (n != -1) {
deba@57
   935
        e.id = nodes[n].first_out;
deba@57
   936
        while ((e.id & 1) != 1) {
deba@57
   937
          e.id = arcs[e.id].next_out;
deba@57
   938
        }
deba@57
   939
        if (e.id != -1) {
deba@57
   940
          e.id /= 2;
deba@57
   941
          return;
alpar@209
   942
        }
deba@57
   943
        n = nodes[n].next;
deba@57
   944
      }
deba@57
   945
      e.id = -1;
deba@57
   946
    }
deba@57
   947
deba@57
   948
    void firstOut(Arc &e, const Node& v) const {
deba@57
   949
      e.id = nodes[v.id].first_out;
deba@57
   950
    }
deba@57
   951
    void nextOut(Arc &e) const {
deba@57
   952
      e.id = arcs[e.id].next_out;
deba@57
   953
    }
deba@57
   954
deba@57
   955
    void firstIn(Arc &e, const Node& v) const {
deba@57
   956
      e.id = ((nodes[v.id].first_out) ^ 1);
deba@57
   957
      if (e.id == -2) e.id = -1;
deba@57
   958
    }
deba@57
   959
    void nextIn(Arc &e) const {
deba@57
   960
      e.id = ((arcs[e.id ^ 1].next_out) ^ 1);
deba@57
   961
      if (e.id == -2) e.id = -1;
deba@57
   962
    }
deba@57
   963
deba@57
   964
    void firstInc(Edge &e, bool& d, const Node& v) const {
kpeter@73
   965
      int a = nodes[v.id].first_out;
kpeter@73
   966
      if (a != -1 ) {
kpeter@73
   967
        e.id = a / 2;
kpeter@73
   968
        d = ((a & 1) == 1);
deba@57
   969
      } else {
deba@57
   970
        e.id = -1;
deba@57
   971
        d = true;
deba@57
   972
      }
deba@57
   973
    }
deba@57
   974
    void nextInc(Edge &e, bool& d) const {
kpeter@73
   975
      int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
kpeter@73
   976
      if (a != -1 ) {
kpeter@73
   977
        e.id = a / 2;
kpeter@73
   978
        d = ((a & 1) == 1);
deba@57
   979
      } else {
deba@57
   980
        e.id = -1;
deba@57
   981
        d = true;
deba@57
   982
      }
deba@57
   983
    }
alpar@209
   984
deba@57
   985
    static int id(Node v) { return v.id; }
deba@57
   986
    static int id(Arc e) { return e.id; }
deba@57
   987
    static int id(Edge e) { return e.id; }
deba@57
   988
deba@57
   989
    static Node nodeFromId(int id) { return Node(id);}
deba@57
   990
    static Arc arcFromId(int id) { return Arc(id);}
deba@57
   991
    static Edge edgeFromId(int id) { return Edge(id);}
deba@57
   992
alpar@209
   993
    bool valid(Node n) const {
alpar@209
   994
      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
alpar@209
   995
        nodes[n.id].prev != -2;
deba@149
   996
    }
deba@149
   997
alpar@209
   998
    bool valid(Arc a) const {
alpar@209
   999
      return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
alpar@209
  1000
        arcs[a.id].prev_out != -2;
deba@149
  1001
    }
deba@149
  1002
alpar@209
  1003
    bool valid(Edge e) const {
alpar@209
  1004
      return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) &&
alpar@209
  1005
        arcs[2 * e.id].prev_out != -2;
deba@149
  1006
    }
deba@149
  1007
alpar@209
  1008
    Node addNode() {
deba@57
  1009
      int n;
alpar@209
  1010
deba@57
  1011
      if(first_free_node==-1) {
alpar@209
  1012
        n = nodes.size();
alpar@209
  1013
        nodes.push_back(NodeT());
deba@57
  1014
      } else {
alpar@209
  1015
        n = first_free_node;
alpar@209
  1016
        first_free_node = nodes[n].next;
deba@57
  1017
      }
alpar@209
  1018
deba@57
  1019
      nodes[n].next = first_node;
deba@57
  1020
      if (first_node != -1) nodes[first_node].prev = n;
deba@57
  1021
      first_node = n;
deba@57
  1022
      nodes[n].prev = -1;
alpar@209
  1023
deba@57
  1024
      nodes[n].first_out = -1;
alpar@209
  1025
deba@57
  1026
      return Node(n);
deba@57
  1027
    }
alpar@209
  1028
deba@57
  1029
    Edge addEdge(Node u, Node v) {
alpar@209
  1030
      int n;
deba@57
  1031
deba@57
  1032
      if (first_free_arc == -1) {
alpar@209
  1033
        n = arcs.size();
alpar@209
  1034
        arcs.push_back(ArcT());
alpar@209
  1035
        arcs.push_back(ArcT());
deba@57
  1036
      } else {
alpar@209
  1037
        n = first_free_arc;
alpar@209
  1038
        first_free_arc = arcs[n].next_out;
deba@57
  1039
      }
alpar@209
  1040
deba@57
  1041
      arcs[n].target = u.id;
deba@57
  1042
      arcs[n | 1].target = v.id;
deba@57
  1043
deba@57
  1044
      arcs[n].next_out = nodes[v.id].first_out;
deba@57
  1045
      if (nodes[v.id].first_out != -1) {
alpar@209
  1046
        arcs[nodes[v.id].first_out].prev_out = n;
alpar@209
  1047
      }
deba@57
  1048
      arcs[n].prev_out = -1;
deba@57
  1049
      nodes[v.id].first_out = n;
alpar@209
  1050
deba@57
  1051
      arcs[n | 1].next_out = nodes[u.id].first_out;
deba@57
  1052
      if (nodes[u.id].first_out != -1) {
alpar@209
  1053
        arcs[nodes[u.id].first_out].prev_out = (n | 1);
deba@57
  1054
      }
alpar@209
  1055
      arcs[n | 1].prev_out = -1;
deba@57
  1056
      nodes[u.id].first_out = (n | 1);
deba@57
  1057
deba@57
  1058
      return Edge(n / 2);
deba@57
  1059
    }
alpar@209
  1060
deba@57
  1061
    void erase(const Node& node) {
deba@57
  1062
      int n = node.id;
alpar@209
  1063
deba@57
  1064
      if(nodes[n].next != -1) {
alpar@209
  1065
        nodes[nodes[n].next].prev = nodes[n].prev;
deba@57
  1066
      }
alpar@209
  1067
deba@57
  1068
      if(nodes[n].prev != -1) {
alpar@209
  1069
        nodes[nodes[n].prev].next = nodes[n].next;
deba@57
  1070
      } else {
alpar@209
  1071
        first_node = nodes[n].next;
deba@57
  1072
      }
alpar@209
  1073
deba@57
  1074
      nodes[n].next = first_free_node;
deba@57
  1075
      first_free_node = n;
deba@149
  1076
      nodes[n].prev = -2;
deba@57
  1077
    }
alpar@209
  1078
kpeter@73
  1079
    void erase(const Edge& edge) {
kpeter@73
  1080
      int n = edge.id * 2;
alpar@209
  1081
deba@57
  1082
      if (arcs[n].next_out != -1) {
alpar@209
  1083
        arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
alpar@209
  1084
      }
deba@57
  1085
deba@57
  1086
      if (arcs[n].prev_out != -1) {
alpar@209
  1087
        arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
deba@57
  1088
      } else {
alpar@209
  1089
        nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
deba@57
  1090
      }
deba@57
  1091
deba@57
  1092
      if (arcs[n | 1].next_out != -1) {
alpar@209
  1093
        arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
alpar@209
  1094
      }
deba@57
  1095
deba@57
  1096
      if (arcs[n | 1].prev_out != -1) {
alpar@209
  1097
        arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
deba@57
  1098
      } else {
alpar@209
  1099
        nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
deba@57
  1100
      }
alpar@209
  1101
deba@57
  1102
      arcs[n].next_out = first_free_arc;
alpar@209
  1103
      first_free_arc = n;
deba@149
  1104
      arcs[n].prev_out = -2;
deba@149
  1105
      arcs[n | 1].prev_out = -2;
deba@57
  1106
deba@57
  1107
    }
deba@57
  1108
deba@57
  1109
    void clear() {
deba@57
  1110
      arcs.clear();
deba@57
  1111
      nodes.clear();
deba@57
  1112
      first_node = first_free_node = first_free_arc = -1;
deba@57
  1113
    }
deba@57
  1114
deba@57
  1115
  protected:
deba@57
  1116
deba@235
  1117
    void changeV(Edge e, Node n) {
deba@57
  1118
      if(arcs[2 * e.id].next_out != -1) {
alpar@209
  1119
        arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
deba@57
  1120
      }
deba@57
  1121
      if(arcs[2 * e.id].prev_out != -1) {
alpar@209
  1122
        arcs[arcs[2 * e.id].prev_out].next_out =
deba@57
  1123
          arcs[2 * e.id].next_out;
deba@57
  1124
      } else {
alpar@209
  1125
        nodes[arcs[(2 * e.id) | 1].target].first_out =
deba@57
  1126
          arcs[2 * e.id].next_out;
deba@57
  1127
      }
deba@57
  1128
deba@57
  1129
      if (nodes[n.id].first_out != -1) {
alpar@209
  1130
        arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
deba@57
  1131
      }
deba@57
  1132
      arcs[(2 * e.id) | 1].target = n.id;
deba@57
  1133
      arcs[2 * e.id].prev_out = -1;
deba@57
  1134
      arcs[2 * e.id].next_out = nodes[n.id].first_out;
deba@57
  1135
      nodes[n.id].first_out = 2 * e.id;
deba@57
  1136
    }
deba@57
  1137
deba@235
  1138
    void changeU(Edge e, Node n) {
deba@57
  1139
      if(arcs[(2 * e.id) | 1].next_out != -1) {
alpar@209
  1140
        arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
deba@57
  1141
          arcs[(2 * e.id) | 1].prev_out;
deba@57
  1142
      }
deba@57
  1143
      if(arcs[(2 * e.id) | 1].prev_out != -1) {
alpar@209
  1144
        arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
deba@57
  1145
          arcs[(2 * e.id) | 1].next_out;
deba@57
  1146
      } else {
alpar@209
  1147
        nodes[arcs[2 * e.id].target].first_out =
deba@57
  1148
          arcs[(2 * e.id) | 1].next_out;
deba@57
  1149
      }
deba@57
  1150
deba@57
  1151
      if (nodes[n.id].first_out != -1) {
alpar@209
  1152
        arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
deba@57
  1153
      }
deba@57
  1154
      arcs[2 * e.id].target = n.id;
deba@57
  1155
      arcs[(2 * e.id) | 1].prev_out = -1;
deba@57
  1156
      arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
deba@57
  1157
      nodes[n.id].first_out = ((2 * e.id) | 1);
deba@57
  1158
    }
deba@57
  1159
deba@57
  1160
  };
deba@57
  1161
deba@57
  1162
  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
deba@57
  1163
deba@57
  1164
kpeter@73
  1165
  /// \addtogroup graphs
deba@57
  1166
  /// @{
deba@57
  1167
kpeter@73
  1168
  ///A general undirected graph structure.
deba@57
  1169
alpar@209
  1170
  ///\ref ListGraph is a simple and fast <em>undirected graph</em>
alpar@209
  1171
  ///implementation based on static linked lists that are stored in
alpar@209
  1172
  ///\c std::vector structures.
deba@57
  1173
  ///
kpeter@73
  1174
  ///It conforms to the \ref concepts::Graph "Graph concept" and it
kpeter@73
  1175
  ///also provides several useful additional functionalities.
kpeter@73
  1176
  ///Most of the member functions and nested classes are documented
kpeter@73
  1177
  ///only in the concept class.
kpeter@73
  1178
  ///
kpeter@73
  1179
  ///An important extra feature of this graph implementation is that
deba@57
  1180
  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
deba@57
  1181
  ///
kpeter@73
  1182
  ///\sa concepts::Graph
kpeter@73
  1183
deba@57
  1184
  class ListGraph : public ExtendedListGraphBase {
deba@57
  1185
  private:
kpeter@73
  1186
    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
deba@57
  1187
kpeter@73
  1188
    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
deba@57
  1189
    ///
deba@57
  1190
    ListGraph(const ListGraph &) :ExtendedListGraphBase()  {};
deba@57
  1191
    ///\brief Assignment of ListGraph to another one is \e not allowed.
kpeter@73
  1192
    ///Use copyGraph() instead.
deba@57
  1193
deba@57
  1194
    ///Assignment of ListGraph to another one is \e not allowed.
kpeter@73
  1195
    ///Use copyGraph() instead.
deba@57
  1196
    void operator=(const ListGraph &) {}
deba@57
  1197
  public:
deba@57
  1198
    /// Constructor
alpar@209
  1199
deba@57
  1200
    /// Constructor.
deba@57
  1201
    ///
deba@57
  1202
    ListGraph() {}
deba@57
  1203
deba@57
  1204
    typedef ExtendedListGraphBase Parent;
deba@57
  1205
kpeter@73
  1206
    typedef Parent::OutArcIt IncEdgeIt;
deba@57
  1207
kpeter@73
  1208
    /// \brief Add a new node to the graph.
deba@57
  1209
    ///
kpeter@73
  1210
    /// Add a new node to the graph.
deba@57
  1211
    /// \return the new node.
deba@57
  1212
    Node addNode() { return Parent::addNode(); }
deba@57
  1213
kpeter@73
  1214
    /// \brief Add a new edge to the graph.
deba@57
  1215
    ///
kpeter@73
  1216
    /// Add a new edge to the graph with source node \c s
deba@57
  1217
    /// and target node \c t.
deba@57
  1218
    /// \return the new edge.
alpar@209
  1219
    Edge addEdge(const Node& s, const Node& t) {
alpar@209
  1220
      return Parent::addEdge(s, t);
deba@57
  1221
    }
deba@234
  1222
deba@234
  1223
    /// \brief Erase a node from the graph.
deba@234
  1224
    ///
deba@234
  1225
    /// Erase a node from the graph.
deba@234
  1226
    ///
deba@234
  1227
    void erase(const Node& n) { Parent::erase(n); }
deba@234
  1228
deba@234
  1229
    /// \brief Erase an edge from the graph.
deba@234
  1230
    ///
deba@234
  1231
    /// Erase an edge from the graph.
deba@234
  1232
    ///
deba@234
  1233
    void erase(const Edge& e) { Parent::erase(e); }
deba@149
  1234
    /// Node validity check
deba@149
  1235
deba@149
  1236
    /// This function gives back true if the given node is valid,
alpar@209
  1237
    /// ie. it is a real node of the graph.
deba@149
  1238
    ///
deba@149
  1239
    /// \warning A Node pointing to a removed item
deba@149
  1240
    /// could become valid again later if new nodes are
deba@149
  1241
    /// added to the graph.
deba@149
  1242
    bool valid(Node n) const { return Parent::valid(n); }
deba@149
  1243
    /// Arc validity check
deba@149
  1244
deba@149
  1245
    /// This function gives back true if the given arc is valid,
alpar@209
  1246
    /// ie. it is a real arc of the graph.
deba@149
  1247
    ///
deba@149
  1248
    /// \warning An Arc pointing to a removed item
deba@149
  1249
    /// could become valid again later if new edges are
deba@149
  1250
    /// added to the graph.
deba@149
  1251
    bool valid(Arc a) const { return Parent::valid(a); }
deba@149
  1252
    /// Edge validity check
deba@149
  1253
deba@149
  1254
    /// This function gives back true if the given edge is valid,
alpar@209
  1255
    /// ie. it is a real arc of the graph.
deba@149
  1256
    ///
deba@149
  1257
    /// \warning A Edge pointing to a removed item
deba@149
  1258
    /// could become valid again later if new edges are
deba@149
  1259
    /// added to the graph.
deba@149
  1260
    bool valid(Edge e) const { return Parent::valid(e); }
deba@235
  1261
    /// \brief Change the end \c u of \c e to \c n
deba@57
  1262
    ///
deba@235
  1263
    /// This function changes the end \c u of \c e to node \c n.
deba@57
  1264
    ///
deba@235
  1265
    ///\note The <tt>EdgeIt</tt>s and <tt>ArcIt</tt>s referencing the
deba@235
  1266
    ///changed edge are invalidated and if the changed node is the
deba@235
  1267
    ///base node of an iterator then this iterator is also
deba@235
  1268
    ///invalidated.
kpeter@73
  1269
    ///
kpeter@73
  1270
    ///\warning This functionality cannot be used together with the
kpeter@73
  1271
    ///Snapshot feature.
deba@235
  1272
    void changeU(Edge e, Node n) {
deba@235
  1273
      Parent::changeU(e,n);
alpar@209
  1274
    }
deba@235
  1275
    /// \brief Change the end \c v of \c e to \c n
deba@57
  1276
    ///
deba@235
  1277
    /// This function changes the end \c v of \c e to \c n.
deba@57
  1278
    ///
deba@235
  1279
    ///\note The <tt>EdgeIt</tt>s referencing the changed edge remain
deba@235
  1280
    ///valid, however <tt>ArcIt</tt>s and if the changed node is the
deba@235
  1281
    ///base node of an iterator then this iterator is invalidated.
kpeter@73
  1282
    ///
kpeter@73
  1283
    ///\warning This functionality cannot be used together with the
kpeter@73
  1284
    ///Snapshot feature.
deba@235
  1285
    void changeV(Edge e, Node n) {
deba@235
  1286
      Parent::changeV(e,n);
deba@57
  1287
    }
deba@57
  1288
    /// \brief Contract two nodes.
deba@57
  1289
    ///
deba@57
  1290
    /// This function contracts two nodes.
deba@57
  1291
    /// Node \p b will be removed but instead of deleting
deba@57
  1292
    /// its neighboring arcs, they will be joined to \p a.
deba@57
  1293
    /// The last parameter \p r controls whether to remove loops. \c true
deba@57
  1294
    /// means that loops will be removed.
deba@57
  1295
    ///
deba@57
  1296
    /// \note The <tt>ArcIt</tt>s referencing a moved arc remain
deba@57
  1297
    /// valid.
kpeter@73
  1298
    ///
kpeter@73
  1299
    ///\warning This functionality cannot be used together with the
kpeter@73
  1300
    ///Snapshot feature.
deba@57
  1301
    void contract(Node a, Node b, bool r = true) {
kpeter@73
  1302
      for(IncEdgeIt e(*this, b); e!=INVALID;) {
alpar@209
  1303
        IncEdgeIt f = e; ++f;
alpar@209
  1304
        if (r && runningNode(e) == a) {
alpar@209
  1305
          erase(e);
deba@235
  1306
        } else if (u(e) == b) {
deba@235
  1307
          changeU(e, a);
alpar@209
  1308
        } else {
deba@235
  1309
          changeV(e, a);
alpar@209
  1310
        }
alpar@209
  1311
        e = f;
deba@57
  1312
      }
deba@57
  1313
      erase(b);
deba@57
  1314
    }
deba@57
  1315
deba@57
  1316
kpeter@73
  1317
    /// \brief Class to make a snapshot of the graph and restore
kpeter@73
  1318
    /// it later.
deba@57
  1319
    ///
kpeter@73
  1320
    /// Class to make a snapshot of the graph and restore it later.
deba@57
  1321
    ///
deba@57
  1322
    /// The newly added nodes and edges can be removed
deba@57
  1323
    /// using the restore() function.
deba@57
  1324
    ///
kpeter@73
  1325
    /// \warning Edge and node deletions and other modifications
alpar@209
  1326
    /// (e.g. changing nodes of edges, contracting nodes) cannot be
kpeter@73
  1327
    /// restored. These events invalidate the snapshot.
deba@57
  1328
    class Snapshot {
deba@57
  1329
    protected:
deba@57
  1330
deba@57
  1331
      typedef Parent::NodeNotifier NodeNotifier;
deba@57
  1332
deba@57
  1333
      class NodeObserverProxy : public NodeNotifier::ObserverBase {
deba@57
  1334
      public:
deba@57
  1335
deba@57
  1336
        NodeObserverProxy(Snapshot& _snapshot)
deba@57
  1337
          : snapshot(_snapshot) {}
deba@57
  1338
deba@57
  1339
        using NodeNotifier::ObserverBase::attach;
deba@57
  1340
        using NodeNotifier::ObserverBase::detach;
deba@57
  1341
        using NodeNotifier::ObserverBase::attached;
alpar@209
  1342
deba@57
  1343
      protected:
alpar@209
  1344
deba@57
  1345
        virtual void add(const Node& node) {
deba@57
  1346
          snapshot.addNode(node);
deba@57
  1347
        }
deba@57
  1348
        virtual void add(const std::vector<Node>& nodes) {
deba@57
  1349
          for (int i = nodes.size() - 1; i >= 0; ++i) {
deba@57
  1350
            snapshot.addNode(nodes[i]);
deba@57
  1351
          }
deba@57
  1352
        }
deba@57
  1353
        virtual void erase(const Node& node) {
deba@57
  1354
          snapshot.eraseNode(node);
deba@57
  1355
        }
deba@57
  1356
        virtual void erase(const std::vector<Node>& nodes) {
deba@57
  1357
          for (int i = 0; i < int(nodes.size()); ++i) {
deba@57
  1358
            snapshot.eraseNode(nodes[i]);
deba@57
  1359
          }
deba@57
  1360
        }
deba@57
  1361
        virtual void build() {
deba@57
  1362
          Node node;
deba@57
  1363
          std::vector<Node> nodes;
alpar@209
  1364
          for (notifier()->first(node); node != INVALID;
deba@57
  1365
               notifier()->next(node)) {
deba@57
  1366
            nodes.push_back(node);
deba@57
  1367
          }
deba@57
  1368
          for (int i = nodes.size() - 1; i >= 0; --i) {
deba@57
  1369
            snapshot.addNode(nodes[i]);
deba@57
  1370
          }
deba@57
  1371
        }
deba@57
  1372
        virtual void clear() {
deba@57
  1373
          Node node;
alpar@209
  1374
          for (notifier()->first(node); node != INVALID;
deba@57
  1375
               notifier()->next(node)) {
deba@57
  1376
            snapshot.eraseNode(node);
deba@57
  1377
          }
deba@57
  1378
        }
deba@57
  1379
deba@57
  1380
        Snapshot& snapshot;
deba@57
  1381
      };
deba@57
  1382
deba@57
  1383
      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
deba@57
  1384
      public:
deba@57
  1385
deba@57
  1386
        EdgeObserverProxy(Snapshot& _snapshot)
deba@57
  1387
          : snapshot(_snapshot) {}
deba@57
  1388
deba@57
  1389
        using EdgeNotifier::ObserverBase::attach;
deba@57
  1390
        using EdgeNotifier::ObserverBase::detach;
deba@57
  1391
        using EdgeNotifier::ObserverBase::attached;
alpar@209
  1392
deba@57
  1393
      protected:
deba@57
  1394
kpeter@73
  1395
        virtual void add(const Edge& edge) {
kpeter@73
  1396
          snapshot.addEdge(edge);
deba@57
  1397
        }
kpeter@73
  1398
        virtual void add(const std::vector<Edge>& edges) {
kpeter@73
  1399
          for (int i = edges.size() - 1; i >= 0; ++i) {
kpeter@73
  1400
            snapshot.addEdge(edges[i]);
deba@57
  1401
          }
deba@57
  1402
        }
kpeter@73
  1403
        virtual void erase(const Edge& edge) {
kpeter@73
  1404
          snapshot.eraseEdge(edge);
deba@57
  1405
        }
kpeter@73
  1406
        virtual void erase(const std::vector<Edge>& edges) {
kpeter@73
  1407
          for (int i = 0; i < int(edges.size()); ++i) {
kpeter@73
  1408
            snapshot.eraseEdge(edges[i]);
deba@57
  1409
          }
deba@57
  1410
        }
deba@57
  1411
        virtual void build() {
kpeter@73
  1412
          Edge edge;
kpeter@73
  1413
          std::vector<Edge> edges;
alpar@209
  1414
          for (notifier()->first(edge); edge != INVALID;
kpeter@73
  1415
               notifier()->next(edge)) {
kpeter@73
  1416
            edges.push_back(edge);
deba@57
  1417
          }
kpeter@73
  1418
          for (int i = edges.size() - 1; i >= 0; --i) {
kpeter@73
  1419
            snapshot.addEdge(edges[i]);
deba@57
  1420
          }
deba@57
  1421
        }
deba@57
  1422
        virtual void clear() {
kpeter@73
  1423
          Edge edge;
alpar@209
  1424
          for (notifier()->first(edge); edge != INVALID;
kpeter@73
  1425
               notifier()->next(edge)) {
kpeter@73
  1426
            snapshot.eraseEdge(edge);
deba@57
  1427
          }
deba@57
  1428
        }
deba@57
  1429
deba@57
  1430
        Snapshot& snapshot;
deba@57
  1431
      };
kpeter@73
  1432
kpeter@73
  1433
      ListGraph *graph;
deba@57
  1434
deba@57
  1435
      NodeObserverProxy node_observer_proxy;
kpeter@73
  1436
      EdgeObserverProxy edge_observer_proxy;
deba@57
  1437
deba@57
  1438
      std::list<Node> added_nodes;
kpeter@73
  1439
      std::list<Edge> added_edges;
deba@57
  1440
deba@57
  1441
deba@57
  1442
      void addNode(const Node& node) {
alpar@209
  1443
        added_nodes.push_front(node);
deba@57
  1444
      }
deba@57
  1445
      void eraseNode(const Node& node) {
alpar@209
  1446
        std::list<Node>::iterator it =
deba@57
  1447
          std::find(added_nodes.begin(), added_nodes.end(), node);
deba@57
  1448
        if (it == added_nodes.end()) {
deba@57
  1449
          clear();
kpeter@73
  1450
          edge_observer_proxy.detach();
deba@57
  1451
          throw NodeNotifier::ImmediateDetach();
deba@57
  1452
        } else {
deba@57
  1453
          added_nodes.erase(it);
deba@57
  1454
        }
deba@57
  1455
      }
deba@57
  1456
kpeter@73
  1457
      void addEdge(const Edge& edge) {
alpar@209
  1458
        added_edges.push_front(edge);
deba@57
  1459
      }
kpeter@73
  1460
      void eraseEdge(const Edge& edge) {
alpar@209
  1461
        std::list<Edge>::iterator it =
kpeter@73
  1462
          std::find(added_edges.begin(), added_edges.end(), edge);
kpeter@73
  1463
        if (it == added_edges.end()) {
deba@57
  1464
          clear();
deba@57
  1465
          node_observer_proxy.detach();
deba@57
  1466
          throw EdgeNotifier::ImmediateDetach();
deba@57
  1467
        } else {
kpeter@73
  1468
          added_edges.erase(it);
kpeter@73
  1469
        }
deba@57
  1470
      }
deba@57
  1471
kpeter@73
  1472
      void attach(ListGraph &_graph) {
alpar@209
  1473
        graph = &_graph;
alpar@209
  1474
        node_observer_proxy.attach(graph->notifier(Node()));
kpeter@73
  1475
        edge_observer_proxy.attach(graph->notifier(Edge()));
deba@57
  1476
      }
alpar@209
  1477
deba@57
  1478
      void detach() {
alpar@209
  1479
        node_observer_proxy.detach();
alpar@209
  1480
        edge_observer_proxy.detach();
deba@57
  1481
      }
deba@57
  1482
deba@57
  1483
      bool attached() const {
deba@57
  1484
        return node_observer_proxy.attached();
deba@57
  1485
      }
deba@57
  1486
deba@57
  1487
      void clear() {
deba@57
  1488
        added_nodes.clear();
alpar@209
  1489
        added_edges.clear();
deba@57
  1490
      }
deba@57
  1491
deba@57
  1492
    public:
deba@57
  1493
deba@57
  1494
      /// \brief Default constructor.
deba@57
  1495
      ///
deba@57
  1496
      /// Default constructor.
deba@57
  1497
      /// To actually make a snapshot you must call save().
alpar@209
  1498
      Snapshot()
alpar@209
  1499
        : graph(0), node_observer_proxy(*this),
kpeter@73
  1500
          edge_observer_proxy(*this) {}
alpar@209
  1501
deba@57
  1502
      /// \brief Constructor that immediately makes a snapshot.
alpar@209
  1503
      ///
kpeter@73
  1504
      /// This constructor immediately makes a snapshot of the graph.
kpeter@73
  1505
      /// \param _graph The graph we make a snapshot of.
alpar@209
  1506
      Snapshot(ListGraph &_graph)
alpar@209
  1507
        : node_observer_proxy(*this),
kpeter@73
  1508
          edge_observer_proxy(*this) {
alpar@209
  1509
        attach(_graph);
deba@57
  1510
      }
alpar@209
  1511
deba@57
  1512
      /// \brief Make a snapshot.
deba@57
  1513
      ///
kpeter@73
  1514
      /// Make a snapshot of the graph.
deba@57
  1515
      ///
deba@57
  1516
      /// This function can be called more than once. In case of a repeated
deba@57
  1517
      /// call, the previous snapshot gets lost.
kpeter@73
  1518
      /// \param _graph The graph we make the snapshot of.
kpeter@73
  1519
      void save(ListGraph &_graph) {
deba@57
  1520
        if (attached()) {
deba@57
  1521
          detach();
deba@57
  1522
          clear();
deba@57
  1523
        }
kpeter@73
  1524
        attach(_graph);
deba@57
  1525
      }
alpar@209
  1526
deba@57
  1527
      /// \brief Undo the changes until the last snapshot.
alpar@209
  1528
      //
deba@57
  1529
      /// Undo the changes until the last snapshot created by save().
deba@57
  1530
      void restore() {
alpar@209
  1531
        detach();
alpar@209
  1532
        for(std::list<Edge>::iterator it = added_edges.begin();
kpeter@73
  1533
            it != added_edges.end(); ++it) {
alpar@209
  1534
          graph->erase(*it);
alpar@209
  1535
        }
alpar@209
  1536
        for(std::list<Node>::iterator it = added_nodes.begin();
deba@57
  1537
            it != added_nodes.end(); ++it) {
alpar@209
  1538
          graph->erase(*it);
alpar@209
  1539
        }
deba@57
  1540
        clear();
deba@57
  1541
      }
deba@57
  1542
deba@57
  1543
      /// \brief Gives back true when the snapshot is valid.
deba@57
  1544
      ///
deba@57
  1545
      /// Gives back true when the snapshot is valid.
deba@57
  1546
      bool valid() const {
deba@57
  1547
        return attached();
deba@57
  1548
      }
deba@57
  1549
    };
deba@57
  1550
  };
alpar@209
  1551
alpar@209
  1552
  /// @}
deba@57
  1553
} //namespace lemon
alpar@209
  1554
deba@57
  1555
deba@57
  1556
#endif