src/hugo/skeletons/graph.h
author alpar
Thu, 23 Sep 2004 15:05:20 +0000
changeset 906 17f31d280385
parent 881 a9f19f38970b
child 911 89a4fbb99cad
permissions -rw-r--r--
Copyright header added.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 * src/hugo/skeletons/graph.h - Part of HUGOlib, a generic C++ optimization library
alpar@906
     3
 *
alpar@906
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@906
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@906
    16
alpar@503
    17
#ifndef HUGO_SKELETON_GRAPH_H
alpar@503
    18
#define HUGO_SKELETON_GRAPH_H
alpar@52
    19
alpar@794
    20
///\ingroup skeletons
alpar@242
    21
///\file
alpar@880
    22
///\brief Declaration of Graph.
alpar@242
    23
ladanyi@542
    24
#include <hugo/invalid.h>
alpar@732
    25
#include <hugo/skeletons/maps.h>
alpar@145
    26
alpar@163
    27
namespace hugo {
alpar@732
    28
  namespace skeleton {
alpar@732
    29
    
alpar@794
    30
    /// \addtogroup skeletons
alpar@794
    31
    /// @{
alpar@163
    32
alpar@732
    33
    /// An empty static graph class.
alpar@732
    34
  
alpar@732
    35
    /// This class provides all the common features of a graph structure,
alpar@732
    36
    /// however completely without implementations and real data structures
alpar@732
    37
    /// behind the interface.
alpar@732
    38
    /// All graph algorithms should compile with this class, but it will not
alpar@732
    39
    /// run properly, of course.
alpar@732
    40
    ///
alpar@732
    41
    /// It can be used for checking the interface compatibility,
alpar@732
    42
    /// or it can serve as a skeleton of a new graph structure.
alpar@732
    43
    /// 
alpar@732
    44
    /// Also, you will find here the full documentation of a certain graph
alpar@732
    45
    /// feature, the documentation of a real graph imlementation
alpar@732
    46
    /// like @ref ListGraph or
alpar@732
    47
    /// @ref SmartGraph will just refer to this structure.
alpar@880
    48
    class StaticGraph
alpar@732
    49
    {
alpar@732
    50
    public:
alpar@732
    51
      /// Defalult constructor.
alpar@801
    52
alpar@801
    53
      /// Defalult constructor.
alpar@801
    54
      ///
alpar@880
    55
      StaticGraph() { }
alpar@732
    56
      ///Copy consructor.
alpar@163
    57
alpar@801
    58
//       ///\todo It is not clear, what we expect from a copy constructor.
alpar@801
    59
//       ///E.g. How to assign the nodes/edges to each other? What about maps?
alpar@880
    60
//       StaticGraph(const StaticGraph& g) { }
alpar@732
    61
alpar@774
    62
      /// The base type of node iterators, 
alpar@774
    63
      /// or in other words, the trivial node iterator.
alpar@732
    64
alpar@774
    65
      /// This is the base type of each node iterator,
alpar@774
    66
      /// thus each kind of node iterator converts to this.
alpar@801
    67
      /// More precisely each kind of node iterator should be inherited 
alpar@774
    68
      /// from the trivial node iterator.
alpar@732
    69
      class Node {
alpar@732
    70
      public:
alpar@801
    71
	/// Default constructor
alpar@801
    72
alpar@732
    73
	/// @warning The default constructor sets the iterator
alpar@732
    74
	/// to an undefined value.
alpar@774
    75
	Node() { }
alpar@774
    76
	/// Copy constructor.
alpar@801
    77
alpar@801
    78
	/// Copy constructor.
alpar@801
    79
	///
alpar@774
    80
	Node(const Node&) { }
alpar@801
    81
alpar@732
    82
	/// Invalid constructor \& conversion.
alpar@732
    83
alpar@732
    84
	/// This constructor initializes the iterator to be invalid.
alpar@732
    85
	/// \sa Invalid for more details.
alpar@774
    86
	Node(Invalid) { }
alpar@801
    87
	/// Equality operator
alpar@801
    88
alpar@732
    89
	/// Two iterators are equal if and only if they point to the
alpar@732
    90
	/// same object or both are invalid.
alpar@732
    91
	bool operator==(Node) const { return true; }
alpar@732
    92
alpar@801
    93
	/// Inequality operator
alpar@801
    94
	
alpar@732
    95
	/// \sa \ref operator==(Node n)
alpar@732
    96
	///
alpar@732
    97
	bool operator!=(Node) const { return true; }
alpar@732
    98
alpar@801
    99
 	///Comparison operator.
alpar@801
   100
alpar@801
   101
	///This is a strict ordering between the nodes.
alpar@801
   102
	///
alpar@801
   103
	///This ordering can be different from the order in which NodeIt
alpar@801
   104
	///goes through the nodes.
alpar@801
   105
	///\todo Possibly we don't need it.
alpar@732
   106
	bool operator<(Node) const { return true; }
alpar@732
   107
      };
alpar@732
   108
    
alpar@732
   109
      /// This iterator goes through each node.
alpar@732
   110
alpar@732
   111
      /// This iterator goes through each node.
alpar@732
   112
      /// Its usage is quite simple, for example you can count the number
alpar@774
   113
      /// of nodes in graph \c g of type \c Graph like this:
alpar@732
   114
      /// \code
alpar@774
   115
      /// int count=0;
alpar@801
   116
      /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;
alpar@732
   117
      /// \endcode
alpar@732
   118
      class NodeIt : public Node {
alpar@732
   119
      public:
alpar@801
   120
	/// Default constructor
alpar@801
   121
alpar@732
   122
	/// @warning The default constructor sets the iterator
alpar@732
   123
	/// to an undefined value.
alpar@774
   124
	NodeIt() { }
alpar@774
   125
	/// Copy constructor.
alpar@801
   126
	
alpar@801
   127
	/// Copy constructor.
alpar@801
   128
	///
alpar@774
   129
	NodeIt(const NodeIt&) { }
alpar@732
   130
	/// Invalid constructor \& conversion.
alpar@732
   131
alpar@774
   132
	/// Initialize the iterator to be invalid.
alpar@732
   133
	/// \sa Invalid for more details.
alpar@774
   134
	NodeIt(Invalid) { }
alpar@801
   135
	/// Sets the iterator to the first node.
alpar@801
   136
alpar@774
   137
	/// Sets the iterator to the first node of \c g.
alpar@801
   138
	///
alpar@880
   139
	NodeIt(const StaticGraph& g) { }
alpar@801
   140
	/// Node -> NodeIt conversion.
alpar@801
   141
alpar@774
   142
	/// Sets the iterator to the node of \c g pointed by the trivial 
alpar@801
   143
	/// iterator n.
alpar@801
   144
	/// This feature necessitates that each time we 
alpar@801
   145
	/// iterate the edge-set, the iteration order is the same.
alpar@880
   146
	NodeIt(const StaticGraph& g, const Node& n) { }
alpar@801
   147
	/// Next node.
alpar@801
   148
alpar@774
   149
	/// Assign the iterator to the next node.
alpar@801
   150
	///
alpar@774
   151
	NodeIt& operator++() { return *this; }
alpar@732
   152
      };
alpar@732
   153
    
alpar@732
   154
    
alpar@732
   155
      /// The base type of the edge iterators.
alpar@801
   156
alpar@801
   157
      /// The base type of the edge iterators.
alpar@801
   158
      ///
alpar@732
   159
      class Edge {
alpar@732
   160
      public:
alpar@801
   161
	/// Default constructor
alpar@801
   162
alpar@732
   163
	/// @warning The default constructor sets the iterator
alpar@732
   164
	/// to an undefined value.
alpar@774
   165
	Edge() { }
alpar@774
   166
	/// Copy constructor.
alpar@801
   167
alpar@801
   168
	/// Copy constructor.
alpar@801
   169
	///
alpar@774
   170
	Edge(const Edge&) { }
alpar@774
   171
	/// Initialize the iterator to be invalid.
alpar@801
   172
alpar@801
   173
	/// Initialize the iterator to be invalid.
alpar@801
   174
	///
alpar@774
   175
	Edge(Invalid) { }
alpar@801
   176
	/// Equality operator
alpar@801
   177
alpar@732
   178
	/// Two iterators are equal if and only if they point to the
alpar@732
   179
	/// same object or both are invalid.
alpar@732
   180
	bool operator==(Edge) const { return true; }
alpar@801
   181
	/// Inequality operator
alpar@801
   182
alpar@801
   183
	/// \sa \ref operator==(Node n)
alpar@801
   184
	///
alpar@732
   185
	bool operator!=(Edge) const { return true; }
alpar@801
   186
 	///Comparison operator.
alpar@801
   187
alpar@801
   188
	///This is a strict ordering between the nodes.
alpar@801
   189
	///
alpar@801
   190
	///This ordering can be different from the order in which NodeIt
alpar@801
   191
	///goes through the nodes.
alpar@801
   192
	///\todo Possibly we don't need it.
alpar@801
   193
 	bool operator<(Edge) const { return true; }
alpar@732
   194
      };
alpar@732
   195
    
alpar@732
   196
      /// This iterator goes trough the outgoing edges of a node.
alpar@732
   197
alpar@732
   198
      /// This iterator goes trough the \e outgoing edges of a certain node
alpar@732
   199
      /// of a graph.
alpar@732
   200
      /// Its usage is quite simple, for example you can count the number
alpar@732
   201
      /// of outgoing edges of a node \c n
alpar@774
   202
      /// in graph \c g of type \c Graph as follows.
alpar@732
   203
      /// \code
alpar@774
   204
      /// int count=0;
alpar@801
   205
      /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count;
alpar@732
   206
      /// \endcode
alpar@732
   207
    
alpar@732
   208
      class OutEdgeIt : public Edge {
alpar@732
   209
      public:
alpar@801
   210
	/// Default constructor
alpar@801
   211
alpar@732
   212
	/// @warning The default constructor sets the iterator
alpar@732
   213
	/// to an undefined value.
alpar@774
   214
	OutEdgeIt() { }
alpar@774
   215
	/// Copy constructor.
alpar@801
   216
alpar@801
   217
	/// Copy constructor.
alpar@801
   218
	///
alpar@774
   219
	OutEdgeIt(const OutEdgeIt&) { }
alpar@774
   220
	/// Initialize the iterator to be invalid.
alpar@801
   221
alpar@801
   222
	/// Initialize the iterator to be invalid.
alpar@801
   223
	///
alpar@774
   224
	OutEdgeIt(Invalid) { }
alpar@732
   225
	/// This constructor sets the iterator to first outgoing edge.
alpar@732
   226
    
alpar@732
   227
	/// This constructor set the iterator to the first outgoing edge of
alpar@732
   228
	/// node
alpar@732
   229
	///@param n the node
alpar@774
   230
	///@param g the graph
alpar@880
   231
	OutEdgeIt(const StaticGraph& g, const Node& n) { }
alpar@801
   232
	/// Edge -> OutEdgeIt conversion
alpar@801
   233
alpar@774
   234
	/// Sets the iterator to the value of the trivial iterator \c e.
alpar@774
   235
	/// This feature necessitates that each time we 
alpar@774
   236
	/// iterate the edge-set, the iteration order is the same.
alpar@880
   237
	OutEdgeIt(const StaticGraph& g, const Edge& e) { }
alpar@801
   238
	///Next outgoing edge
alpar@801
   239
	
alpar@801
   240
	/// Assign the iterator to the next 
alpar@801
   241
	/// outgoing edge of the corresponding node.
alpar@774
   242
	OutEdgeIt& operator++() { return *this; }
alpar@732
   243
      };
alpar@732
   244
alpar@732
   245
      /// This iterator goes trough the incoming edges of a node.
alpar@732
   246
alpar@732
   247
      /// This iterator goes trough the \e incoming edges of a certain node
alpar@732
   248
      /// of a graph.
alpar@732
   249
      /// Its usage is quite simple, for example you can count the number
alpar@732
   250
      /// of outgoing edges of a node \c n
alpar@774
   251
      /// in graph \c g of type \c Graph as follows.
alpar@732
   252
      /// \code
alpar@774
   253
      /// int count=0;
alpar@801
   254
      /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count;
alpar@732
   255
      /// \endcode
alpar@732
   256
alpar@732
   257
      class InEdgeIt : public Edge {
alpar@732
   258
      public:
alpar@801
   259
	/// Default constructor
alpar@801
   260
alpar@732
   261
	/// @warning The default constructor sets the iterator
alpar@732
   262
	/// to an undefined value.
alpar@774
   263
	InEdgeIt() { }
alpar@774
   264
	/// Copy constructor.
alpar@801
   265
alpar@801
   266
	/// Copy constructor.
alpar@801
   267
	///
alpar@774
   268
	InEdgeIt(const InEdgeIt&) { }
alpar@774
   269
	/// Initialize the iterator to be invalid.
alpar@801
   270
alpar@801
   271
	/// Initialize the iterator to be invalid.
alpar@801
   272
	///
alpar@774
   273
	InEdgeIt(Invalid) { }
alpar@801
   274
	/// This constructor sets the iterator to first incoming edge.
alpar@801
   275
    
alpar@801
   276
	/// This constructor set the iterator to the first incoming edge of
alpar@801
   277
	/// node
alpar@801
   278
	///@param n the node
alpar@801
   279
	///@param g the graph
alpar@880
   280
	InEdgeIt(const StaticGraph& g, const Node& n) { }
alpar@801
   281
	/// Edge -> InEdgeIt conversion
alpar@801
   282
alpar@801
   283
	/// Sets the iterator to the value of the trivial iterator \c e.
alpar@801
   284
	/// This feature necessitates that each time we 
alpar@801
   285
	/// iterate the edge-set, the iteration order is the same.
alpar@880
   286
	InEdgeIt(const StaticGraph& g, const Edge& n) { }
alpar@801
   287
	/// Next incoming edge
alpar@801
   288
alpar@774
   289
	/// Assign the iterator to the next inedge of the corresponding node.
alpar@801
   290
	///
alpar@774
   291
	InEdgeIt& operator++() { return *this; }
alpar@732
   292
      };
alpar@732
   293
      /// This iterator goes through each edge.
alpar@732
   294
alpar@732
   295
      /// This iterator goes through each edge of a graph.
alpar@732
   296
      /// Its usage is quite simple, for example you can count the number
alpar@774
   297
      /// of edges in a graph \c g of type \c Graph as follows:
alpar@732
   298
      /// \code
alpar@774
   299
      /// int count=0;
alpar@801
   300
      /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;
alpar@732
   301
      /// \endcode
alpar@732
   302
      class EdgeIt : public Edge {
alpar@732
   303
      public:
alpar@801
   304
	/// Default constructor
alpar@801
   305
alpar@732
   306
	/// @warning The default constructor sets the iterator
alpar@732
   307
	/// to an undefined value.
alpar@774
   308
	EdgeIt() { }
alpar@774
   309
	/// Copy constructor.
alpar@801
   310
alpar@801
   311
	/// Copy constructor.
alpar@801
   312
	///
alpar@774
   313
	EdgeIt(const EdgeIt&) { }
alpar@774
   314
	/// Initialize the iterator to be invalid.
alpar@801
   315
alpar@801
   316
	/// Initialize the iterator to be invalid.
alpar@801
   317
	///
alpar@774
   318
	EdgeIt(Invalid) { }
alpar@801
   319
	/// This constructor sets the iterator to first edge.
alpar@801
   320
    
alpar@801
   321
	/// This constructor set the iterator to the first edge of
alpar@801
   322
	/// node
alpar@801
   323
	///@param g the graph
alpar@880
   324
	EdgeIt(const StaticGraph& g) { }
alpar@801
   325
	/// Edge -> EdgeIt conversion
alpar@801
   326
alpar@801
   327
	/// Sets the iterator to the value of the trivial iterator \c e.
alpar@801
   328
	/// This feature necessitates that each time we 
alpar@801
   329
	/// iterate the edge-set, the iteration order is the same.
alpar@880
   330
	EdgeIt(const StaticGraph&, const Edge&) { } 
alpar@801
   331
    	///Next edge
alpar@801
   332
	
alpar@801
   333
	/// Assign the iterator to the next 
alpar@801
   334
	/// edge of the corresponding node.
alpar@774
   335
	EdgeIt& operator++() { return *this; }
alpar@732
   336
      };
alpar@732
   337
alpar@732
   338
      /// First node of the graph.
alpar@732
   339
alpar@732
   340
      /// \retval i the first node.
alpar@732
   341
      /// \return the first node.
alpar@732
   342
      ///
alpar@774
   343
      NodeIt& first(NodeIt& i) const { return i; }
alpar@732
   344
alpar@732
   345
      /// The first incoming edge.
alpar@801
   346
alpar@801
   347
      /// The first incoming edge.
alpar@801
   348
      ///
alpar@774
   349
      InEdgeIt& first(InEdgeIt &i, Node) const { return i; }
alpar@732
   350
      /// The first outgoing edge.
alpar@801
   351
alpar@801
   352
      /// The first outgoing edge.
alpar@801
   353
      ///
alpar@774
   354
      OutEdgeIt& first(OutEdgeIt& i, Node) const { return i; }
alpar@732
   355
      /// The first edge of the Graph.
alpar@801
   356
alpar@801
   357
      /// The first edge of the Graph.
alpar@801
   358
      ///
alpar@774
   359
      EdgeIt& first(EdgeIt& i) const { return i; }
alpar@732
   360
alpar@801
   361
      ///Gives back the head node of an edge.
alpar@732
   362
alpar@732
   363
      ///Gives back the head node of an edge.
alpar@801
   364
      ///
alpar@732
   365
      Node head(Edge) const { return INVALID; }
alpar@732
   366
      ///Gives back the tail node of an edge.
alpar@801
   367
alpar@801
   368
      ///Gives back the tail node of an edge.
alpar@801
   369
      ///
alpar@732
   370
      Node tail(Edge) const { return INVALID; }
alpar@163
   371
  
alpar@732
   372
      ///Gives back the \e id of a node.
alpar@182
   373
alpar@732
   374
      ///\warning Not all graph structures provide this feature.
alpar@732
   375
      ///
alpar@801
   376
      ///\todo Should each graph provide \c id?
alpar@774
   377
      int id(const Node&) const { return 0; }
alpar@732
   378
      ///Gives back the \e id of an edge.
alpar@182
   379
alpar@732
   380
      ///\warning Not all graph structures provide this feature.
alpar@182
   381
      ///
alpar@801
   382
      ///\todo Should each graph provide \c id?
alpar@774
   383
      int id(const Edge&) const { return 0; }
alpar@182
   384
alpar@801
   385
      /// .
alpar@801
   386
      
alpar@880
   387
      ///\todo Should it be in the concept?
alpar@801
   388
      ///
alpar@774
   389
      int nodeNum() const { return 0; }
alpar@801
   390
      /// .
alpar@880
   391
alpar@880
   392
      ///\todo Should it be in the concept?
alpar@801
   393
      ///
alpar@774
   394
      int edgeNum() const { return 0; }
alpar@732
   395
alpar@732
   396
alpar@732
   397
      ///Reference map of the nodes to type \c T.
alpar@732
   398
alpar@880
   399
      /// \ingroup skeletons
alpar@732
   400
      ///Reference map of the nodes to type \c T.
alpar@880
   401
      /// \sa Reference
alpar@732
   402
      /// \warning Making maps that can handle bool type (NodeMap<bool>)
alpar@801
   403
      /// needs some extra attention!
alpar@880
   404
      template<class T> class NodeMap : public ReferenceMap< Node, T >
alpar@732
   405
      {
alpar@732
   406
      public:
alpar@732
   407
alpar@801
   408
	/// .
alpar@880
   409
	NodeMap(const StaticGraph&) { }
alpar@801
   410
	/// .
alpar@880
   411
	NodeMap(const StaticGraph&, T) { }
alpar@732
   412
alpar@732
   413
	///Copy constructor
alpar@774
   414
	template<typename TT> NodeMap(const NodeMap<TT>&) { }
alpar@732
   415
	///Assignment operator
alpar@774
   416
	template<typename TT> NodeMap& operator=(const NodeMap<TT>&)
alpar@774
   417
	{ return *this; }
alpar@732
   418
      };
alpar@732
   419
alpar@732
   420
      ///Reference map of the edges to type \c T.
alpar@732
   421
alpar@880
   422
      /// \ingroup skeletons
alpar@732
   423
      ///Reference map of the edges to type \c T.
alpar@880
   424
      /// \sa Reference
alpar@732
   425
      /// \warning Making maps that can handle bool type (EdgeMap<bool>)
alpar@801
   426
      /// needs some extra attention!
alpar@732
   427
      template<class T> class EdgeMap
alpar@732
   428
	: public ReferenceMap<Edge,T>
alpar@732
   429
      {
alpar@732
   430
      public:
alpar@732
   431
alpar@801
   432
	/// .
alpar@880
   433
	EdgeMap(const StaticGraph&) { }
alpar@801
   434
	/// .
alpar@880
   435
	EdgeMap(const StaticGraph&, T) { }
alpar@147
   436
    
alpar@732
   437
	///Copy constructor
alpar@774
   438
	template<typename TT> EdgeMap(const EdgeMap<TT>&) { }
alpar@732
   439
	///Assignment operator
alpar@774
   440
	template<typename TT> EdgeMap &operator=(const EdgeMap<TT>&)
alpar@774
   441
	{ return *this; }
alpar@732
   442
      };
alpar@163
   443
    };
alpar@163
   444
alpar@186
   445
alpar@732
   446
  
alpar@801
   447
    /// An empty non-static graph class.
alpar@186
   448
alpar@880
   449
    /// This class provides everything that \ref StaticGraph
alpar@732
   450
    /// with additional functionality which enables to build a
alpar@732
   451
    /// graph from scratch.
alpar@880
   452
    class ExtendableGraph : public StaticGraph
alpar@732
   453
    {
alpar@163
   454
    public:
alpar@732
   455
      /// Defalult constructor.
alpar@801
   456
alpar@801
   457
      /// Defalult constructor.
alpar@801
   458
      ///
alpar@880
   459
      ExtendableGraph() { }
alpar@732
   460
      ///Add a new node to the graph.
alpar@732
   461
alpar@732
   462
      /// \return the new node.
alpar@732
   463
      ///
alpar@774
   464
      Node addNode() { return INVALID; }
alpar@732
   465
      ///Add a new edge to the graph.
alpar@732
   466
alpar@880
   467
      ///Add a new edge to the graph with tail node \c t
alpar@880
   468
      ///and head node \c h.
alpar@732
   469
      ///\return the new edge.
alpar@880
   470
      Edge addEdge(Node h, Node t) { return INVALID; }
alpar@732
   471
    
alpar@732
   472
      /// Resets the graph.
alpar@732
   473
alpar@732
   474
      /// This function deletes all edges and nodes of the graph.
alpar@732
   475
      /// It also frees the memory allocated to store them.
alpar@880
   476
      /// \todo It might belong to \ref ErasableGraph.
alpar@774
   477
      void clear() { }
alpar@163
   478
    };
alpar@163
   479
alpar@826
   480
    /// An empty erasable graph class.
alpar@52
   481
  
alpar@880
   482
    /// This class is an extension of \ref ExtendableGraph. It also makes it
alpar@732
   483
    /// possible to erase edges or nodes.
alpar@880
   484
    class ErasableGraph : public ExtendableGraph
alpar@163
   485
    {
alpar@163
   486
    public:
alpar@801
   487
      /// Defalult constructor.
alpar@801
   488
alpar@801
   489
      /// Defalult constructor.
alpar@801
   490
      ///
alpar@880
   491
      ErasableGraph() { }
alpar@732
   492
      /// Deletes a node.
alpar@801
   493
alpar@801
   494
      /// Deletes node \c n node.
alpar@801
   495
      ///
alpar@774
   496
      void erase(Node n) { }
alpar@732
   497
      /// Deletes an edge.
alpar@801
   498
alpar@801
   499
      /// Deletes edge \c e edge.
alpar@801
   500
      ///
alpar@774
   501
      void erase(Edge e) { }
alpar@163
   502
    };
alpar@163
   503
alpar@732
   504
    // @}
alpar@801
   505
  } //namespace skeleton  
marci@174
   506
} //namespace hugo
alpar@52
   507
alpar@145
   508
alpar@145
   509
alpar@503
   510
#endif // HUGO_SKELETON_GRAPH_H