COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/skeletons/graph.h @ 938:70e2886211d5

Last change on this file since 938:70e2886211d5 was 938:70e2886211d5, checked in by Alpar Juttner, 16 years ago

Many of ckeckCompileXYZ()'s are now in the corresponding skeleton headers.
(Tests for Symmetric Graphs are still to be moved)

File size: 20.4 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/skeletons/graph.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17#ifndef LEMON_SKELETON_GRAPH_H
18#define LEMON_SKELETON_GRAPH_H
19
20///\ingroup skeletons
21///\file
22///\brief Declaration of Graph.
23
24#include <lemon/invalid.h>
25#include <lemon/skeletons/maps.h>
26
27namespace lemon {
28  namespace skeleton {
29   
30    /// \addtogroup skeletons
31    /// @{
32
33    /// An empty static graph class.
34 
35    /// This class provides all the common features of a graph structure,
36    /// however completely without implementations and real data structures
37    /// behind the interface.
38    /// All graph algorithms should compile with this class, but it will not
39    /// run properly, of course.
40    ///
41    /// It can be used for checking the interface compatibility,
42    /// or it can serve as a skeleton of a new graph structure.
43    ///
44    /// Also, you will find here the full documentation of a certain graph
45    /// feature, the documentation of a real graph imlementation
46    /// like @ref ListGraph or
47    /// @ref SmartGraph will just refer to this structure.
48    ///
49    /// \todo A pages describing the concept of concept description would
50    /// be nice.
51    class StaticGraph
52    {
53    public:
54      /// Defalult constructor.
55
56      /// Defalult constructor.
57      ///
58      StaticGraph() { }
59      ///Copy consructor.
60
61//       ///\todo It is not clear, what we expect from a copy constructor.
62//       ///E.g. How to assign the nodes/edges to each other? What about maps?
63//       StaticGraph(const StaticGraph& g) { }
64
65      /// The base type of node iterators,
66      /// or in other words, the trivial node iterator.
67
68      /// This is the base type of each node iterator,
69      /// thus each kind of node iterator converts to this.
70      /// More precisely each kind of node iterator should be inherited
71      /// from the trivial node iterator.
72      class Node {
73      public:
74        /// Default constructor
75
76        /// @warning The default constructor sets the iterator
77        /// to an undefined value.
78        Node() { }
79        /// Copy constructor.
80
81        /// Copy constructor.
82        ///
83        Node(const Node&) { }
84
85        /// Invalid constructor \& conversion.
86
87        /// This constructor initializes the iterator to be invalid.
88        /// \sa Invalid for more details.
89        Node(Invalid) { }
90        /// Equality operator
91
92        /// Two iterators are equal if and only if they point to the
93        /// same object or both are invalid.
94        bool operator==(Node) const { return true; }
95
96        /// Inequality operator
97       
98        /// \sa operator==(Node n)
99        ///
100        bool operator!=(Node) const { return true; }
101
102        ///Comparison operator.
103
104        ///This is a strict ordering between the nodes.
105        ///
106        ///This ordering can be different from the order in which NodeIt
107        ///goes through the nodes.
108        ///\todo Possibly we don't need it.
109        bool operator<(Node) const { return true; }
110      };
111   
112      /// This iterator goes through each node.
113
114      /// This iterator goes through each node.
115      /// Its usage is quite simple, for example you can count the number
116      /// of nodes in graph \c g of type \c Graph like this:
117      /// \code
118      /// int count=0;
119      /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;
120      /// \endcode
121      class NodeIt : public Node {
122      public:
123        /// Default constructor
124
125        /// @warning The default constructor sets the iterator
126        /// to an undefined value.
127        NodeIt() { }
128        /// Copy constructor.
129       
130        /// Copy constructor.
131        ///
132        NodeIt(const NodeIt&) { }
133        /// Invalid constructor \& conversion.
134
135        /// Initialize the iterator to be invalid.
136        /// \sa Invalid for more details.
137        NodeIt(Invalid) { }
138        /// Sets the iterator to the first node.
139
140        /// Sets the iterator to the first node of \c g.
141        ///
142        NodeIt(const StaticGraph& g) { }
143        /// Node -> NodeIt conversion.
144
145        /// Sets the iterator to the node of \c g pointed by the trivial
146        /// iterator n.
147        /// This feature necessitates that each time we
148        /// iterate the edge-set, the iteration order is the same.
149        NodeIt(const StaticGraph& g, const Node& n) { }
150        /// Next node.
151
152        /// Assign the iterator to the next node.
153        ///
154        NodeIt& operator++() { return *this; }
155      };
156   
157   
158      /// The base type of the edge iterators.
159
160      /// The base type of the edge iterators.
161      ///
162      class Edge {
163      public:
164        /// Default constructor
165
166        /// @warning The default constructor sets the iterator
167        /// to an undefined value.
168        Edge() { }
169        /// Copy constructor.
170
171        /// Copy constructor.
172        ///
173        Edge(const Edge&) { }
174        /// Initialize the iterator to be invalid.
175
176        /// Initialize the iterator to be invalid.
177        ///
178        Edge(Invalid) { }
179        /// Equality operator
180
181        /// Two iterators are equal if and only if they point to the
182        /// same object or both are invalid.
183        bool operator==(Edge) const { return true; }
184        /// Inequality operator
185
186        /// \sa operator==(Node n)
187        ///
188        bool operator!=(Edge) const { return true; }
189        ///Comparison operator.
190
191        ///This is a strict ordering between the nodes.
192        ///
193        ///This ordering can be different from the order in which NodeIt
194        ///goes through the nodes.
195        ///\todo Possibly we don't need it.
196        bool operator<(Edge) const { return true; }
197      };
198   
199      /// This iterator goes trough the outgoing edges of a node.
200
201      /// This iterator goes trough the \e outgoing edges of a certain node
202      /// of a graph.
203      /// Its usage is quite simple, for example you can count the number
204      /// of outgoing edges of a node \c n
205      /// in graph \c g of type \c Graph as follows.
206      /// \code
207      /// int count=0;
208      /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count;
209      /// \endcode
210   
211      class OutEdgeIt : public Edge {
212      public:
213        /// Default constructor
214
215        /// @warning The default constructor sets the iterator
216        /// to an undefined value.
217        OutEdgeIt() { }
218        /// Copy constructor.
219
220        /// Copy constructor.
221        ///
222        OutEdgeIt(const OutEdgeIt&) { }
223        /// Initialize the iterator to be invalid.
224
225        /// Initialize the iterator to be invalid.
226        ///
227        OutEdgeIt(Invalid) { }
228        /// This constructor sets the iterator to first outgoing edge.
229   
230        /// This constructor set the iterator to the first outgoing edge of
231        /// node
232        ///@param n the node
233        ///@param g the graph
234        OutEdgeIt(const StaticGraph& g, const Node& n) { }
235        /// Edge -> OutEdgeIt conversion
236
237        /// Sets the iterator to the value of the trivial iterator \c e.
238        /// This feature necessitates that each time we
239        /// iterate the edge-set, the iteration order is the same.
240        OutEdgeIt(const StaticGraph& g, const Edge& e) { }
241        ///Next outgoing edge
242       
243        /// Assign the iterator to the next
244        /// outgoing edge of the corresponding node.
245        OutEdgeIt& operator++() { return *this; }
246      };
247
248      /// This iterator goes trough the incoming edges of a node.
249
250      /// This iterator goes trough the \e incoming edges of a certain node
251      /// of a graph.
252      /// Its usage is quite simple, for example you can count the number
253      /// of outgoing edges of a node \c n
254      /// in graph \c g of type \c Graph as follows.
255      /// \code
256      /// int count=0;
257      /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count;
258      /// \endcode
259
260      class InEdgeIt : public Edge {
261      public:
262        /// Default constructor
263
264        /// @warning The default constructor sets the iterator
265        /// to an undefined value.
266        InEdgeIt() { }
267        /// Copy constructor.
268
269        /// Copy constructor.
270        ///
271        InEdgeIt(const InEdgeIt&) { }
272        /// Initialize the iterator to be invalid.
273
274        /// Initialize the iterator to be invalid.
275        ///
276        InEdgeIt(Invalid) { }
277        /// This constructor sets the iterator to first incoming edge.
278   
279        /// This constructor set the iterator to the first incoming edge of
280        /// node
281        ///@param n the node
282        ///@param g the graph
283        InEdgeIt(const StaticGraph& g, const Node& n) { }
284        /// Edge -> InEdgeIt conversion
285
286        /// Sets the iterator to the value of the trivial iterator \c e.
287        /// This feature necessitates that each time we
288        /// iterate the edge-set, the iteration order is the same.
289        InEdgeIt(const StaticGraph& g, const Edge& n) { }
290        /// Next incoming edge
291
292        /// Assign the iterator to the next inedge of the corresponding node.
293        ///
294        InEdgeIt& operator++() { return *this; }
295      };
296      /// This iterator goes through each edge.
297
298      /// This iterator goes through each edge of a graph.
299      /// Its usage is quite simple, for example you can count the number
300      /// of edges in a graph \c g of type \c Graph as follows:
301      /// \code
302      /// int count=0;
303      /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;
304      /// \endcode
305      class EdgeIt : public Edge {
306      public:
307        /// Default constructor
308
309        /// @warning The default constructor sets the iterator
310        /// to an undefined value.
311        EdgeIt() { }
312        /// Copy constructor.
313
314        /// Copy constructor.
315        ///
316        EdgeIt(const EdgeIt&) { }
317        /// Initialize the iterator to be invalid.
318
319        /// Initialize the iterator to be invalid.
320        ///
321        EdgeIt(Invalid) { }
322        /// This constructor sets the iterator to first edge.
323   
324        /// This constructor set the iterator to the first edge of
325        /// node
326        ///@param g the graph
327        EdgeIt(const StaticGraph& g) { }
328        /// Edge -> EdgeIt conversion
329
330        /// Sets the iterator to the value of the trivial iterator \c e.
331        /// This feature necessitates that each time we
332        /// iterate the edge-set, the iteration order is the same.
333        EdgeIt(const StaticGraph&, const Edge&) { }
334        ///Next edge
335       
336        /// Assign the iterator to the next
337        /// edge of the corresponding node.
338        EdgeIt& operator++() { return *this; }
339      };
340
341      /// First node of the graph.
342
343      /// \retval i the first node.
344      /// \return the first node.
345      ///
346      NodeIt& first(NodeIt& i) const { return i; }
347
348      /// The first incoming edge.
349
350      /// The first incoming edge.
351      ///
352      InEdgeIt& first(InEdgeIt &i, Node) const { return i; }
353      /// The first outgoing edge.
354
355      /// The first outgoing edge.
356      ///
357      OutEdgeIt& first(OutEdgeIt& i, Node) const { return i; }
358      /// The first edge of the Graph.
359
360      /// The first edge of the Graph.
361      ///
362      EdgeIt& first(EdgeIt& i) const { return i; }
363
364      ///Gives back the head node of an edge.
365
366      ///Gives back the head node of an edge.
367      ///
368      Node head(Edge) const { return INVALID; }
369      ///Gives back the tail node of an edge.
370
371      ///Gives back the tail node of an edge.
372      ///
373      Node tail(Edge) const { return INVALID; }
374 
375      ///Gives back the \e id of a node.
376
377      ///\warning Not all graph structures provide this feature.
378      ///
379      ///\todo Should each graph provide \c id?
380      int id(const Node&) const { return 0; }
381      ///Gives back the \e id of an edge.
382
383      ///\warning Not all graph structures provide this feature.
384      ///
385      ///\todo Should each graph provide \c id?
386      int id(const Edge&) const { return 0; }
387
388      ///\e
389     
390      ///\todo Should it be in the concept?
391      ///
392      int nodeNum() const { return 0; }
393      ///\e
394
395      ///\todo Should it be in the concept?
396      ///
397      int edgeNum() const { return 0; }
398
399
400      ///Reference map of the nodes to type \c T.
401
402      /// \ingroup skeletons
403      ///Reference map of the nodes to type \c T.
404      /// \sa Reference
405      /// \warning Making maps that can handle bool type (NodeMap<bool>)
406      /// needs some extra attention!
407      template<class T> class NodeMap : public ReferenceMap< Node, T >
408      {
409      public:
410
411        ///\e
412        NodeMap(const StaticGraph&) { }
413        ///\e
414        NodeMap(const StaticGraph&, T) { }
415
416        ///Copy constructor
417        template<typename TT> NodeMap(const NodeMap<TT>&) { }
418        ///Assignment operator
419        template<typename TT> NodeMap& operator=(const NodeMap<TT>&)
420        { return *this; }
421      };
422
423      ///Reference map of the edges to type \c T.
424
425      /// \ingroup skeletons
426      ///Reference map of the edges to type \c T.
427      /// \sa Reference
428      /// \warning Making maps that can handle bool type (EdgeMap<bool>)
429      /// needs some extra attention!
430      template<class T> class EdgeMap
431        : public ReferenceMap<Edge,T>
432      {
433      public:
434
435        ///\e
436        EdgeMap(const StaticGraph&) { }
437        ///\e
438        EdgeMap(const StaticGraph&, T) { }
439   
440        ///Copy constructor
441        template<typename TT> EdgeMap(const EdgeMap<TT>&) { }
442        ///Assignment operator
443        template<typename TT> EdgeMap &operator=(const EdgeMap<TT>&)
444        { return *this; }
445      };
446    };
447
448    struct DummyType {
449      int value;
450      DummyType() {}
451      DummyType(int p) : value(p) {}
452      DummyType& operator=(int p) { value = p; return *this;}
453    };
454   
455    ///\brief Checks whether \c G meets the
456    ///\ref lemon::skeleton::StaticGraph "StaticGraph" concept
457    template<class Graph> void checkCompileStaticGraph(Graph &G)
458    {
459      typedef typename Graph::Node Node;
460      typedef typename Graph::NodeIt NodeIt;
461      typedef typename Graph::Edge Edge;
462      typedef typename Graph::EdgeIt EdgeIt;
463      typedef typename Graph::InEdgeIt InEdgeIt;
464      typedef typename Graph::OutEdgeIt OutEdgeIt;
465 
466      {
467        Node i; Node j(i); Node k(INVALID);
468        i=j;
469        bool b; b=true;
470        b=(i==INVALID); b=(i!=INVALID);
471        b=(i==j); b=(i!=j); b=(i<j);
472      }
473      {
474        NodeIt i; NodeIt j(i); NodeIt k(INVALID); NodeIt l(G);
475        i=j;
476        j=G.first(i);
477        j=++i;
478        bool b; b=true;
479        b=(i==INVALID); b=(i!=INVALID);
480        Node n(i);
481        n=i;
482        b=(i==j); b=(i!=j); b=(i<j);
483        //Node ->NodeIt conversion
484        NodeIt ni(G,n);
485      }
486      {
487        Edge i; Edge j(i); Edge k(INVALID);
488        i=j;
489        bool b; b=true;
490        b=(i==INVALID); b=(i!=INVALID);
491        b=(i==j); b=(i!=j); b=(i<j);
492      }
493      {
494        EdgeIt i; EdgeIt j(i); EdgeIt k(INVALID); EdgeIt l(G);
495        i=j;
496        j=G.first(i);
497        j=++i;
498        bool b; b=true;
499        b=(i==INVALID); b=(i!=INVALID);
500        Edge e(i);
501        e=i;
502        b=(i==j); b=(i!=j); b=(i<j);
503        //Edge ->EdgeIt conversion
504        EdgeIt ei(G,e);
505      }
506      {
507        Node n;
508        InEdgeIt i; InEdgeIt j(i); InEdgeIt k(INVALID); InEdgeIt l(G,n);
509        i=j;
510        j=G.first(i,n);
511        j=++i;
512        bool b; b=true;
513        b=(i==INVALID); b=(i!=INVALID);
514        Edge e(i);
515        e=i;
516        b=(i==j); b=(i!=j); b=(i<j);
517        //Edge ->InEdgeIt conversion
518        InEdgeIt ei(G,e);
519      }
520      {
521        Node n;
522        OutEdgeIt i; OutEdgeIt j(i); OutEdgeIt k(INVALID); OutEdgeIt l(G,n);
523        i=j;
524        j=G.first(i,n);
525        j=++i;
526        bool b; b=true;
527        b=(i==INVALID); b=(i!=INVALID);
528        Edge e(i);
529        e=i;
530        b=(i==j); b=(i!=j); b=(i<j);
531        //Edge ->OutEdgeIt conversion
532        OutEdgeIt ei(G,e);
533      }
534      {
535        Node n,m;
536        n=m=INVALID;
537        Edge e;
538        e=INVALID;
539        n=G.tail(e);
540        n=G.head(e);
541      }
542      // id tests
543      { Node n; int i=G.id(n); i=i; }
544      { Edge e; int i=G.id(e); i=i; }
545      //NodeMap tests
546      {
547        Node k;
548        typename Graph::template NodeMap<int> m(G);
549        //Const map
550        typename Graph::template NodeMap<int> const &cm = m;
551        //Inicialize with default value
552        typename Graph::template NodeMap<int> mdef(G,12);
553        //Copy
554        typename Graph::template NodeMap<int> mm(cm);
555        //Copy from another type
556        typename Graph::template NodeMap<double> dm(cm);
557        //Copy to more complex type
558        typename Graph::template NodeMap<DummyType> em(cm);
559        int v;
560        v=m[k]; m[k]=v; m.set(k,v);
561        v=cm[k];
562   
563        m=cm; 
564        dm=cm; //Copy from another type 
565        em=cm; //Copy to more complex type
566        {
567          //Check the typedef's
568          typename Graph::template NodeMap<int>::ValueType val;
569          val=1;
570          typename Graph::template NodeMap<int>::KeyType key;
571          key = typename Graph::NodeIt(G);
572        }
573      } 
574      { //bool NodeMap
575        Node k;
576        typename Graph::template NodeMap<bool> m(G);
577        typename Graph::template NodeMap<bool> const &cm = m;  //Const map
578        //Inicialize with default value
579        typename Graph::template NodeMap<bool> mdef(G,12);
580        typename Graph::template NodeMap<bool> mm(cm);   //Copy
581        typename Graph::template NodeMap<int> dm(cm); //Copy from another type
582        bool v;
583        v=m[k]; m[k]=v; m.set(k,v);
584        v=cm[k];
585   
586        m=cm; 
587        dm=cm; //Copy from another type
588        m=dm; //Copy to another type
589
590        {
591          //Check the typedef's
592          typename Graph::template NodeMap<bool>::ValueType val;
593          val=true;
594          typename Graph::template NodeMap<bool>::KeyType key;
595          key= typename Graph::NodeIt(G);
596        }
597      }
598      //EdgeMap tests
599      {
600        Edge k;
601        typename Graph::template EdgeMap<int> m(G);
602        typename Graph::template EdgeMap<int> const &cm = m;  //Const map
603        //Inicialize with default value
604        typename Graph::template EdgeMap<int> mdef(G,12);
605        typename Graph::template EdgeMap<int> mm(cm);   //Copy
606        typename Graph::template EdgeMap<double> dm(cm);//Copy from another type
607        int v;
608        v=m[k]; m[k]=v; m.set(k,v);
609        v=cm[k];
610   
611        m=cm; 
612        dm=cm; //Copy from another type
613        {
614          //Check the typedef's
615          typename Graph::template EdgeMap<int>::ValueType val;
616          val=1;
617          typename Graph::template EdgeMap<int>::KeyType key;
618          key= typename Graph::EdgeIt(G);
619        }
620      } 
621      { //bool EdgeMap
622        Edge k;
623        typename Graph::template EdgeMap<bool> m(G);
624        typename Graph::template EdgeMap<bool> const &cm = m;  //Const map
625        //Inicialize with default value
626        typename Graph::template EdgeMap<bool> mdef(G,12);
627        typename Graph::template EdgeMap<bool> mm(cm);   //Copy
628        typename Graph::template EdgeMap<int> dm(cm); //Copy from another type
629        bool v;
630        v=m[k]; m[k]=v; m.set(k,v);
631        v=cm[k];
632   
633        m=cm; 
634        dm=cm; //Copy from another type
635        m=dm; //Copy to another type
636        {
637          //Check the typedef's
638          typename Graph::template EdgeMap<bool>::ValueType val;
639          val=true;
640          typename Graph::template EdgeMap<bool>::KeyType key;
641          key= typename Graph::EdgeIt(G);
642        }
643      }
644    }
645   
646    /// An empty non-static graph class.
647   
648    /// This class provides everything that \ref StaticGraph
649    /// with additional functionality which enables to build a
650    /// graph from scratch.
651    class ExtendableGraph : public StaticGraph
652    {
653    public:
654      /// Defalult constructor.
655
656      /// Defalult constructor.
657      ///
658      ExtendableGraph() { }
659      ///Add a new node to the graph.
660
661      /// \return the new node.
662      ///
663      Node addNode() { return INVALID; }
664      ///Add a new edge to the graph.
665
666      ///Add a new edge to the graph with tail node \c t
667      ///and head node \c h.
668      ///\return the new edge.
669      Edge addEdge(Node h, Node t) { return INVALID; }
670   
671      /// Resets the graph.
672
673      /// This function deletes all edges and nodes of the graph.
674      /// It also frees the memory allocated to store them.
675      /// \todo It might belong to \ref ErasableGraph.
676      void clear() { }
677    };
678
679   
680    ///\brief Checks whether \c G meets the
681    ///\ref lemon::skeleton::ExtendableGraph "ExtendableGraph" concept
682    template<class Graph> void checkCompileExtendableGraph(Graph &G)
683    {
684      checkCompileStaticGraph(G);
685
686      typedef typename Graph::Node Node;
687      typedef typename Graph::NodeIt NodeIt;
688      typedef typename Graph::Edge Edge;
689      typedef typename Graph::EdgeIt EdgeIt;
690      typedef typename Graph::InEdgeIt InEdgeIt;
691      typedef typename Graph::OutEdgeIt OutEdgeIt;
692 
693      Node n,m;
694      n=G.addNode();
695      m=G.addNode();
696      Edge e;
697      e=G.addEdge(n,m);
698 
699      //  G.clear();
700    }
701
702
703    /// An empty erasable graph class.
704 
705    /// This class is an extension of \ref ExtendableGraph. It also makes it
706    /// possible to erase edges or nodes.
707    class ErasableGraph : public ExtendableGraph
708    {
709    public:
710      /// Defalult constructor.
711
712      /// Defalult constructor.
713      ///
714      ErasableGraph() { }
715      /// Deletes a node.
716
717      /// Deletes node \c n node.
718      ///
719      void erase(Node n) { }
720      /// Deletes an edge.
721
722      /// Deletes edge \c e edge.
723      ///
724      void erase(Edge e) { }
725    };
726   
727    template<class Graph> void checkCompileGraphEraseEdge(Graph &G)
728    {
729      typename Graph::Edge e;
730      G.erase(e);
731    }
732
733    template<class Graph> void checkCompileGraphEraseNode(Graph &G)
734    {
735      typename Graph::Node n;
736      G.erase(n);
737    }
738
739    ///\brief Checks whether \c G meets the
740    ///\ref lemon::skeleton::EresableGraph "EresableGraph" concept
741    template<class Graph> void checkCompileErasableGraph(Graph &G)
742    {
743      checkCompileExtendableGraph(G);
744      checkCompileGraphEraseNode(G);
745      checkCompileGraphEraseEdge(G);
746    }
747
748    ///Checks whether a graph has findEdge() member function.
749   
750    ///\todo findEdge() might be a global function.
751    ///
752    template<class Graph> void checkCompileGraphFindEdge(Graph &G)
753    {
754      typedef typename Graph::NodeIt Node;
755      typedef typename Graph::NodeIt NodeIt;
756
757      G.findEdge(NodeIt(G),++NodeIt(G),G.findEdge(NodeIt(G),++NodeIt(G)));
758      G.findEdge(Node(),Node(),G.findEdge(Node(),Node())); 
759    }
760 
761    // @}
762  } //namespace skeleton 
763} //namespace lemon
764
765
766
767#endif // LEMON_SKELETON_GRAPH_H
Note: See TracBrowser for help on using the repository browser.