COIN-OR::LEMON - Graph Library

source: lemon/lemon/smart_graph.h @ 149:2f7ae34e1333

Last change on this file since 149:2f7ae34e1333 was 149:2f7ae34e1333, checked in by Balazs Dezso <deba@…>, 12 years ago

Item validity checking for ListGraph? and SmartGraph?

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