lemon/smart_graph.h
 author Alpar Juttner Fri, 07 Nov 2008 07:18:37 +0000 changeset 384 164fe3abc024 parent 380 a7e8ad460d66 parent 382 00c8843d491d child 388 2d87dbd7f8c8 permissions -rw-r--r--
Merge
     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-2008

     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].target].first_out=arcs[n].next_out;

   741         nodes[arcs[n-1].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