lemon/smart_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 596 8c3112a66878
parent 375 2d87dbd7f8c8
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).
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2009
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_SMART_GRAPH_H
    20 #define LEMON_SMART_GRAPH_H
    21 
    22 ///\ingroup graphs
    23 ///\file
    24 ///\brief SmartDigraph and SmartGraph classes.
    25 
    26 #include <vector>
    27 
    28 #include <lemon/core.h>
    29 #include <lemon/error.h>
    30 #include <lemon/bits/graph_extender.h>
    31 
    32 namespace lemon {
    33 
    34   class SmartDigraph;
    35   ///Base of SmartDigraph
    36 
    37   ///Base of SmartDigraph
    38   ///
    39   class SmartDigraphBase {
    40   protected:
    41 
    42     struct NodeT
    43     {
    44       int first_in, first_out;
    45       NodeT() {}
    46     };
    47     struct ArcT
    48     {
    49       int target, source, next_in, next_out;
    50       ArcT() {}
    51     };
    52 
    53     std::vector<NodeT> nodes;
    54     std::vector<ArcT> arcs;
    55 
    56   public:
    57 
    58     typedef SmartDigraphBase Graph;
    59 
    60     class Node;
    61     class Arc;
    62 
    63   public:
    64 
    65     SmartDigraphBase() : nodes(), arcs() { }
    66     SmartDigraphBase(const SmartDigraphBase &_g)
    67       : nodes(_g.nodes), arcs(_g.arcs) { }
    68 
    69     typedef True NodeNumTag;
    70     typedef True ArcNumTag;
    71 
    72     int nodeNum() const { return nodes.size(); }
    73     int arcNum() const { return arcs.size(); }
    74 
    75     int maxNodeId() const { return nodes.size()-1; }
    76     int maxArcId() const { return arcs.size()-1; }
    77 
    78     Node addNode() {
    79       int n = nodes.size();
    80       nodes.push_back(NodeT());
    81       nodes[n].first_in = -1;
    82       nodes[n].first_out = -1;
    83       return Node(n);
    84     }
    85 
    86     Arc addArc(Node u, Node v) {
    87       int n = arcs.size();
    88       arcs.push_back(ArcT());
    89       arcs[n].source = u._id;
    90       arcs[n].target = v._id;
    91       arcs[n].next_out = nodes[u._id].first_out;
    92       arcs[n].next_in = nodes[v._id].first_in;
    93       nodes[u._id].first_out = nodes[v._id].first_in = n;
    94 
    95       return Arc(n);
    96     }
    97 
    98     void clear() {
    99       arcs.clear();
   100       nodes.clear();
   101     }
   102 
   103     Node source(Arc a) const { return Node(arcs[a._id].source); }
   104     Node target(Arc a) const { return Node(arcs[a._id].target); }
   105 
   106     static int id(Node v) { return v._id; }
   107     static int id(Arc a) { return a._id; }
   108 
   109     static Node nodeFromId(int id) { return Node(id);}
   110     static Arc arcFromId(int id) { return Arc(id);}
   111 
   112     bool valid(Node n) const {
   113       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   114     }
   115     bool valid(Arc a) const {
   116       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   117     }
   118 
   119     class Node {
   120       friend class SmartDigraphBase;
   121       friend class SmartDigraph;
   122 
   123     protected:
   124       int _id;
   125       explicit Node(int id) : _id(id) {}
   126     public:
   127       Node() {}
   128       Node (Invalid) : _id(-1) {}
   129       bool operator==(const Node i) const {return _id == i._id;}
   130       bool operator!=(const Node i) const {return _id != i._id;}
   131       bool operator<(const Node i) const {return _id < i._id;}
   132     };
   133 
   134 
   135     class Arc {
   136       friend class SmartDigraphBase;
   137       friend class SmartDigraph;
   138 
   139     protected:
   140       int _id;
   141       explicit Arc(int id) : _id(id) {}
   142     public:
   143       Arc() { }
   144       Arc (Invalid) : _id(-1) {}
   145       bool operator==(const Arc i) const {return _id == i._id;}
   146       bool operator!=(const Arc i) const {return _id != i._id;}
   147       bool operator<(const Arc i) const {return _id < i._id;}
   148     };
   149 
   150     void first(Node& node) const {
   151       node._id = nodes.size() - 1;
   152     }
   153 
   154     static void next(Node& node) {
   155       --node._id;
   156     }
   157 
   158     void first(Arc& arc) const {
   159       arc._id = arcs.size() - 1;
   160     }
   161 
   162     static void next(Arc& arc) {
   163       --arc._id;
   164     }
   165 
   166     void firstOut(Arc& arc, const Node& node) const {
   167       arc._id = nodes[node._id].first_out;
   168     }
   169 
   170     void nextOut(Arc& arc) const {
   171       arc._id = arcs[arc._id].next_out;
   172     }
   173 
   174     void firstIn(Arc& arc, const Node& node) const {
   175       arc._id = nodes[node._id].first_in;
   176     }
   177 
   178     void nextIn(Arc& arc) const {
   179       arc._id = arcs[arc._id].next_in;
   180     }
   181 
   182   };
   183 
   184   typedef DigraphExtender<SmartDigraphBase> ExtendedSmartDigraphBase;
   185 
   186   ///\ingroup graphs
   187   ///
   188   ///\brief A smart directed graph class.
   189   ///
   190   ///This is a simple and fast digraph implementation.
   191   ///It is also quite memory efficient, but at the price
   192   ///that <b> it does support only limited (only stack-like)
   193   ///node and arc deletions</b>.
   194   ///It conforms to the \ref concepts::Digraph "Digraph concept" with
   195   ///an important extra feature that its maps are real \ref
   196   ///concepts::ReferenceMap "reference map"s.
   197   ///
   198   ///\sa concepts::Digraph.
   199   class SmartDigraph : public ExtendedSmartDigraphBase {
   200   public:
   201 
   202     typedef ExtendedSmartDigraphBase Parent;
   203 
   204   private:
   205 
   206     ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
   207 
   208     ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
   209     ///
   210     SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
   211     ///\brief Assignment of SmartDigraph to another one is \e not allowed.
   212     ///Use DigraphCopy() instead.
   213 
   214     ///Assignment of SmartDigraph to another one is \e not allowed.
   215     ///Use DigraphCopy() instead.
   216     void operator=(const SmartDigraph &) {}
   217 
   218   public:
   219 
   220     /// Constructor
   221 
   222     /// Constructor.
   223     ///
   224     SmartDigraph() {};
   225 
   226     ///Add a new node to the digraph.
   227 
   228     /// \return the new node.
   229     ///
   230     Node addNode() { return Parent::addNode(); }
   231 
   232     ///Add a new arc to the digraph.
   233 
   234     ///Add a new arc to the digraph with source node \c s
   235     ///and target node \c t.
   236     ///\return the new arc.
   237     Arc addArc(const Node& s, const Node& t) {
   238       return Parent::addArc(s, t);
   239     }
   240 
   241     /// \brief Using this it is possible to avoid the superfluous memory
   242     /// allocation.
   243 
   244     /// Using this it is possible to avoid the superfluous memory
   245     /// allocation: if you know that the digraph you want to build will
   246     /// be very large (e.g. it will contain millions of nodes and/or arcs)
   247     /// then it is worth reserving space for this amount before starting
   248     /// to build the digraph.
   249     /// \sa reserveArc
   250     void reserveNode(int n) { nodes.reserve(n); };
   251 
   252     /// \brief Using this it is possible to avoid the superfluous memory
   253     /// allocation.
   254 
   255     /// Using this it is possible to avoid the superfluous memory
   256     /// allocation: if you know that the digraph you want to build will
   257     /// be very large (e.g. it will contain millions of nodes and/or arcs)
   258     /// then it is worth reserving space for this amount before starting
   259     /// to build the digraph.
   260     /// \sa reserveNode
   261     void reserveArc(int m) { arcs.reserve(m); };
   262 
   263     /// \brief Node validity check
   264     ///
   265     /// This function gives back true if the given node is valid,
   266     /// ie. it is a real node of the graph.
   267     ///
   268     /// \warning A removed node (using Snapshot) could become valid again
   269     /// when new nodes are added to the graph.
   270     bool valid(Node n) const { return Parent::valid(n); }
   271 
   272     /// \brief Arc validity check
   273     ///
   274     /// This function gives back true if the given arc is valid,
   275     /// ie. it is a real arc of the graph.
   276     ///
   277     /// \warning A removed arc (using Snapshot) could become valid again
   278     /// when new arcs are added to the graph.
   279     bool valid(Arc a) const { return Parent::valid(a); }
   280 
   281     ///Clear the digraph.
   282 
   283     ///Erase all the nodes and arcs from the digraph.
   284     ///
   285     void clear() {
   286       Parent::clear();
   287     }
   288 
   289     ///Split a node.
   290 
   291     ///This function splits a node. First a new node is added to the digraph,
   292     ///then the source of each outgoing arc of \c n is moved to this new node.
   293     ///If \c connect is \c true (this is the default value), then a new arc
   294     ///from \c n to the newly created node is also added.
   295     ///\return The newly created node.
   296     ///
   297     ///\note The <tt>Arc</tt>s
   298     ///referencing a moved arc remain
   299     ///valid. However <tt>InArc</tt>'s and <tt>OutArc</tt>'s
   300     ///may be invalidated.
   301     ///\warning This functionality cannot be used together with the Snapshot
   302     ///feature.
   303     Node split(Node n, bool connect = true)
   304     {
   305       Node b = addNode();
   306       nodes[b._id].first_out=nodes[n._id].first_out;
   307       nodes[n._id].first_out=-1;
   308       for(int i=nodes[b._id].first_out; i!=-1; i=arcs[i].next_out) {
   309         arcs[i].source=b._id;
   310       }
   311       if(connect) addArc(n,b);
   312       return b;
   313     }
   314 
   315   public:
   316 
   317     class Snapshot;
   318 
   319   protected:
   320 
   321     void restoreSnapshot(const Snapshot &s)
   322     {
   323       while(s.arc_num<arcs.size()) {
   324         Arc arc = arcFromId(arcs.size()-1);
   325         Parent::notifier(Arc()).erase(arc);
   326         nodes[arcs.back().source].first_out=arcs.back().next_out;
   327         nodes[arcs.back().target].first_in=arcs.back().next_in;
   328         arcs.pop_back();
   329       }
   330       while(s.node_num<nodes.size()) {
   331         Node node = nodeFromId(nodes.size()-1);
   332         Parent::notifier(Node()).erase(node);
   333         nodes.pop_back();
   334       }
   335     }
   336 
   337   public:
   338 
   339     ///Class to make a snapshot of the digraph and to restrore to it later.
   340 
   341     ///Class to make a snapshot of the digraph and to restrore to it later.
   342     ///
   343     ///The newly added nodes and arcs can be removed using the
   344     ///restore() function.
   345     ///\note After you restore a state, you cannot restore
   346     ///a later state, in other word you cannot add again the arcs deleted
   347     ///by restore() using another one Snapshot instance.
   348     ///
   349     ///\warning If you do not use correctly the snapshot that can cause
   350     ///either broken program, invalid state of the digraph, valid but
   351     ///not the restored digraph or no change. Because the runtime performance
   352     ///the validity of the snapshot is not stored.
   353     class Snapshot
   354     {
   355       SmartDigraph *_graph;
   356     protected:
   357       friend class SmartDigraph;
   358       unsigned int node_num;
   359       unsigned int arc_num;
   360     public:
   361       ///Default constructor.
   362 
   363       ///Default constructor.
   364       ///To actually make a snapshot you must call save().
   365       ///
   366       Snapshot() : _graph(0) {}
   367       ///Constructor that immediately makes a snapshot
   368 
   369       ///This constructor immediately makes a snapshot of the digraph.
   370       ///\param graph The digraph we make a snapshot of.
   371       Snapshot(SmartDigraph &graph) : _graph(&graph) {
   372         node_num=_graph->nodes.size();
   373         arc_num=_graph->arcs.size();
   374       }
   375 
   376       ///Make a snapshot.
   377 
   378       ///Make a snapshot of the digraph.
   379       ///
   380       ///This function can be called more than once. In case of a repeated
   381       ///call, the previous snapshot gets lost.
   382       ///\param graph The digraph we make the snapshot of.
   383       void save(SmartDigraph &graph)
   384       {
   385         _graph=&graph;
   386         node_num=_graph->nodes.size();
   387         arc_num=_graph->arcs.size();
   388       }
   389 
   390       ///Undo the changes until a snapshot.
   391 
   392       ///Undo the changes until a snapshot created by save().
   393       ///
   394       ///\note After you restored a state, you cannot restore
   395       ///a later state, in other word you cannot add again the arcs deleted
   396       ///by restore().
   397       void restore()
   398       {
   399         _graph->restoreSnapshot(*this);
   400       }
   401     };
   402   };
   403 
   404 
   405   class SmartGraphBase {
   406 
   407   protected:
   408 
   409     struct NodeT {
   410       int first_out;
   411     };
   412 
   413     struct ArcT {
   414       int target;
   415       int next_out;
   416     };
   417 
   418     std::vector<NodeT> nodes;
   419     std::vector<ArcT> arcs;
   420 
   421     int first_free_arc;
   422 
   423   public:
   424 
   425     typedef SmartGraphBase Digraph;
   426 
   427     class Node;
   428     class Arc;
   429     class Edge;
   430 
   431     class Node {
   432       friend class SmartGraphBase;
   433     protected:
   434 
   435       int _id;
   436       explicit Node(int id) { _id = id;}
   437 
   438     public:
   439       Node() {}
   440       Node (Invalid) { _id = -1; }
   441       bool operator==(const Node& node) const {return _id == node._id;}
   442       bool operator!=(const Node& node) const {return _id != node._id;}
   443       bool operator<(const Node& node) const {return _id < node._id;}
   444     };
   445 
   446     class Edge {
   447       friend class SmartGraphBase;
   448     protected:
   449 
   450       int _id;
   451       explicit Edge(int id) { _id = id;}
   452 
   453     public:
   454       Edge() {}
   455       Edge (Invalid) { _id = -1; }
   456       bool operator==(const Edge& arc) const {return _id == arc._id;}
   457       bool operator!=(const Edge& arc) const {return _id != arc._id;}
   458       bool operator<(const Edge& arc) const {return _id < arc._id;}
   459     };
   460 
   461     class Arc {
   462       friend class SmartGraphBase;
   463     protected:
   464 
   465       int _id;
   466       explicit Arc(int id) { _id = id;}
   467 
   468     public:
   469       operator Edge() const {
   470         return _id != -1 ? edgeFromId(_id / 2) : INVALID;
   471       }
   472 
   473       Arc() {}
   474       Arc (Invalid) { _id = -1; }
   475       bool operator==(const Arc& arc) const {return _id == arc._id;}
   476       bool operator!=(const Arc& arc) const {return _id != arc._id;}
   477       bool operator<(const Arc& arc) const {return _id < arc._id;}
   478     };
   479 
   480 
   481 
   482     SmartGraphBase()
   483       : nodes(), arcs() {}
   484 
   485     typedef True NodeNumTag;
   486     typedef True EdgeNumTag;
   487     typedef True ArcNumTag;
   488 
   489     int nodeNum() const { return nodes.size(); }
   490     int edgeNum() const { return arcs.size() / 2; }
   491     int arcNum() const { return arcs.size(); }
   492 
   493     int maxNodeId() const { return nodes.size()-1; }
   494     int maxEdgeId() const { return arcs.size() / 2 - 1; }
   495     int maxArcId() const { return arcs.size()-1; }
   496 
   497     Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }
   498     Node target(Arc e) const { return Node(arcs[e._id].target); }
   499 
   500     Node u(Edge e) const { return Node(arcs[2 * e._id].target); }
   501     Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }
   502 
   503     static bool direction(Arc e) {
   504       return (e._id & 1) == 1;
   505     }
   506 
   507     static Arc direct(Edge e, bool d) {
   508       return Arc(e._id * 2 + (d ? 1 : 0));
   509     }
   510 
   511     void first(Node& node) const {
   512       node._id = nodes.size() - 1;
   513     }
   514 
   515     void next(Node& node) const {
   516       --node._id;
   517     }
   518 
   519     void first(Arc& arc) const {
   520       arc._id = arcs.size() - 1;
   521     }
   522 
   523     void next(Arc& arc) const {
   524       --arc._id;
   525     }
   526 
   527     void first(Edge& arc) const {
   528       arc._id = arcs.size() / 2 - 1;
   529     }
   530 
   531     void next(Edge& arc) const {
   532       --arc._id;
   533     }
   534 
   535     void firstOut(Arc &arc, const Node& v) const {
   536       arc._id = nodes[v._id].first_out;
   537     }
   538     void nextOut(Arc &arc) const {
   539       arc._id = arcs[arc._id].next_out;
   540     }
   541 
   542     void firstIn(Arc &arc, const Node& v) const {
   543       arc._id = ((nodes[v._id].first_out) ^ 1);
   544       if (arc._id == -2) arc._id = -1;
   545     }
   546     void nextIn(Arc &arc) const {
   547       arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
   548       if (arc._id == -2) arc._id = -1;
   549     }
   550 
   551     void firstInc(Edge &arc, bool& d, const Node& v) const {
   552       int de = nodes[v._id].first_out;
   553       if (de != -1) {
   554         arc._id = de / 2;
   555         d = ((de & 1) == 1);
   556       } else {
   557         arc._id = -1;
   558         d = true;
   559       }
   560     }
   561     void nextInc(Edge &arc, bool& d) const {
   562       int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
   563       if (de != -1) {
   564         arc._id = de / 2;
   565         d = ((de & 1) == 1);
   566       } else {
   567         arc._id = -1;
   568         d = true;
   569       }
   570     }
   571 
   572     static int id(Node v) { return v._id; }
   573     static int id(Arc e) { return e._id; }
   574     static int id(Edge e) { return e._id; }
   575 
   576     static Node nodeFromId(int id) { return Node(id);}
   577     static Arc arcFromId(int id) { return Arc(id);}
   578     static Edge edgeFromId(int id) { return Edge(id);}
   579 
   580     bool valid(Node n) const {
   581       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   582     }
   583     bool valid(Arc a) const {
   584       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   585     }
   586     bool valid(Edge e) const {
   587       return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
   588     }
   589 
   590     Node addNode() {
   591       int n = nodes.size();
   592       nodes.push_back(NodeT());
   593       nodes[n].first_out = -1;
   594 
   595       return Node(n);
   596     }
   597 
   598     Edge addEdge(Node u, Node v) {
   599       int n = arcs.size();
   600       arcs.push_back(ArcT());
   601       arcs.push_back(ArcT());
   602 
   603       arcs[n].target = u._id;
   604       arcs[n | 1].target = v._id;
   605 
   606       arcs[n].next_out = nodes[v._id].first_out;
   607       nodes[v._id].first_out = n;
   608 
   609       arcs[n | 1].next_out = nodes[u._id].first_out;
   610       nodes[u._id].first_out = (n | 1);
   611 
   612       return Edge(n / 2);
   613     }
   614 
   615     void clear() {
   616       arcs.clear();
   617       nodes.clear();
   618     }
   619 
   620   };
   621 
   622   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
   623 
   624   /// \ingroup graphs
   625   ///
   626   /// \brief A smart undirected graph class.
   627   ///
   628   /// This is a simple and fast graph implementation.
   629   /// It is also quite memory efficient, but at the price
   630   /// that <b> it does support only limited (only stack-like)
   631   /// node and arc deletions</b>.
   632   /// Except from this it conforms to
   633   /// the \ref concepts::Graph "Graph concept".
   634   ///
   635   /// It also has an
   636   /// important extra feature that
   637   /// its maps are real \ref concepts::ReferenceMap "reference map"s.
   638   ///
   639   /// \sa concepts::Graph.
   640   ///
   641   class SmartGraph : public ExtendedSmartGraphBase {
   642   private:
   643 
   644     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   645 
   646     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   647     ///
   648     SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
   649 
   650     ///\brief Assignment of SmartGraph to another one is \e not allowed.
   651     ///Use GraphCopy() instead.
   652 
   653     ///Assignment of SmartGraph to another one is \e not allowed.
   654     ///Use GraphCopy() instead.
   655     void operator=(const SmartGraph &) {}
   656 
   657   public:
   658 
   659     typedef ExtendedSmartGraphBase Parent;
   660 
   661     /// Constructor
   662 
   663     /// Constructor.
   664     ///
   665     SmartGraph() {}
   666 
   667     ///Add a new node to the graph.
   668 
   669     /// \return the new node.
   670     ///
   671     Node addNode() { return Parent::addNode(); }
   672 
   673     ///Add a new edge to the graph.
   674 
   675     ///Add a new edge to the graph with node \c s
   676     ///and \c t.
   677     ///\return the new edge.
   678     Edge addEdge(const Node& s, const Node& t) {
   679       return Parent::addEdge(s, t);
   680     }
   681 
   682     /// \brief Node validity check
   683     ///
   684     /// This function gives back true if the given node is valid,
   685     /// ie. it is a real node of the graph.
   686     ///
   687     /// \warning A removed node (using Snapshot) could become valid again
   688     /// when new nodes are added to the graph.
   689     bool valid(Node n) const { return Parent::valid(n); }
   690 
   691     /// \brief Arc validity check
   692     ///
   693     /// This function gives back true if the given arc is valid,
   694     /// ie. it is a real arc of the graph.
   695     ///
   696     /// \warning A removed arc (using Snapshot) could become valid again
   697     /// when new edges are added to the graph.
   698     bool valid(Arc a) const { return Parent::valid(a); }
   699 
   700     /// \brief Edge validity check
   701     ///
   702     /// This function gives back true if the given edge is valid,
   703     /// ie. it is a real edge of the graph.
   704     ///
   705     /// \warning A removed edge (using Snapshot) could become valid again
   706     /// when new edges are added to the graph.
   707     bool valid(Edge e) const { return Parent::valid(e); }
   708 
   709     ///Clear the graph.
   710 
   711     ///Erase all the nodes and edges from the graph.
   712     ///
   713     void clear() {
   714       Parent::clear();
   715     }
   716 
   717   public:
   718 
   719     class Snapshot;
   720 
   721   protected:
   722 
   723     void saveSnapshot(Snapshot &s)
   724     {
   725       s._graph = this;
   726       s.node_num = nodes.size();
   727       s.arc_num = arcs.size();
   728     }
   729 
   730     void restoreSnapshot(const Snapshot &s)
   731     {
   732       while(s.arc_num<arcs.size()) {
   733         int n=arcs.size()-1;
   734         Edge arc=edgeFromId(n/2);
   735         Parent::notifier(Edge()).erase(arc);
   736         std::vector<Arc> dir;
   737         dir.push_back(arcFromId(n));
   738         dir.push_back(arcFromId(n-1));
   739         Parent::notifier(Arc()).erase(dir);
   740         nodes[arcs[n-1].target].first_out=arcs[n].next_out;
   741         nodes[arcs[n].target].first_out=arcs[n-1].next_out;
   742         arcs.pop_back();
   743         arcs.pop_back();
   744       }
   745       while(s.node_num<nodes.size()) {
   746         int n=nodes.size()-1;
   747         Node node = nodeFromId(n);
   748         Parent::notifier(Node()).erase(node);
   749         nodes.pop_back();
   750       }
   751     }
   752 
   753   public:
   754 
   755     ///Class to make a snapshot of the digraph and to restrore to it later.
   756 
   757     ///Class to make a snapshot of the digraph and to restrore to it later.
   758     ///
   759     ///The newly added nodes and arcs can be removed using the
   760     ///restore() function.
   761     ///
   762     ///\note After you restore a state, you cannot restore
   763     ///a later state, in other word you cannot add again the arcs deleted
   764     ///by restore() using another one Snapshot instance.
   765     ///
   766     ///\warning If you do not use correctly the snapshot that can cause
   767     ///either broken program, invalid state of the digraph, valid but
   768     ///not the restored digraph or no change. Because the runtime performance
   769     ///the validity of the snapshot is not stored.
   770     class Snapshot
   771     {
   772       SmartGraph *_graph;
   773     protected:
   774       friend class SmartGraph;
   775       unsigned int node_num;
   776       unsigned int arc_num;
   777     public:
   778       ///Default constructor.
   779 
   780       ///Default constructor.
   781       ///To actually make a snapshot you must call save().
   782       ///
   783       Snapshot() : _graph(0) {}
   784       ///Constructor that immediately makes a snapshot
   785 
   786       ///This constructor immediately makes a snapshot of the digraph.
   787       ///\param graph The digraph we make a snapshot of.
   788       Snapshot(SmartGraph &graph) {
   789         graph.saveSnapshot(*this);
   790       }
   791 
   792       ///Make a snapshot.
   793 
   794       ///Make a snapshot of the graph.
   795       ///
   796       ///This function can be called more than once. In case of a repeated
   797       ///call, the previous snapshot gets lost.
   798       ///\param graph The digraph we make the snapshot of.
   799       void save(SmartGraph &graph)
   800       {
   801         graph.saveSnapshot(*this);
   802       }
   803 
   804       ///Undo the changes until a snapshot.
   805 
   806       ///Undo the changes until a snapshot created by save().
   807       ///
   808       ///\note After you restored a state, you cannot restore
   809       ///a later state, in other word you cannot add again the arcs deleted
   810       ///by restore().
   811       void restore()
   812       {
   813         _graph->restoreSnapshot(*this);
   814       }
   815     };
   816   };
   817 
   818 } //namespace lemon
   819 
   820 
   821 #endif //LEMON_SMART_GRAPH_H