lemon/list_graph.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1984 d4cbd10e1256
child 1995 c1fc2c14a3ae
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
alpar@948
     1
/* -*- C++ -*-
alpar@948
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@948
     8
 *
alpar@948
     9
 * Permission to use, modify and distribute this software is granted
alpar@948
    10
 * provided that this copyright notice appears in all copies. For
alpar@948
    11
 * precise terms see the accompanying LICENSE file.
alpar@948
    12
 *
alpar@948
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@948
    14
 * express or implied, and with no claim as to its suitability for any
alpar@948
    15
 * purpose.
alpar@948
    16
 *
alpar@948
    17
 */
alpar@395
    18
alpar@921
    19
#ifndef LEMON_LIST_GRAPH_H
alpar@921
    20
#define LEMON_LIST_GRAPH_H
alpar@395
    21
alpar@948
    22
///\ingroup graphs
alpar@948
    23
///\file
klao@1909
    24
///\brief ListGraph, ListUGraph classes.
alpar@948
    25
deba@1791
    26
#include <lemon/bits/graph_extender.h>
deba@782
    27
deba@1774
    28
#include <lemon/error.h>
deba@1774
    29
deba@1979
    30
#include <vector>
alpar@1011
    31
#include <list>
deba@782
    32
alpar@921
    33
namespace lemon {
alpar@395
    34
klao@946
    35
  class ListGraphBase {
alpar@406
    36
alpar@949
    37
  protected:
klao@946
    38
    struct NodeT {
deba@1470
    39
      int first_in, first_out;
alpar@397
    40
      int prev, next;
alpar@395
    41
    };
klao@946
    42
 
klao@946
    43
    struct EdgeT {
alpar@986
    44
      int target, source;
alpar@397
    45
      int prev_in, prev_out;
alpar@397
    46
      int next_in, next_out;
alpar@395
    47
    };
alpar@395
    48
alpar@395
    49
    std::vector<NodeT> nodes;
klao@946
    50
alpar@397
    51
    int first_node;
klao@946
    52
alpar@397
    53
    int first_free_node;
klao@946
    54
alpar@395
    55
    std::vector<EdgeT> edges;
klao@946
    56
alpar@397
    57
    int first_free_edge;
alpar@395
    58
    
deba@782
    59
  public:
alpar@395
    60
    
klao@946
    61
    typedef ListGraphBase Graph;
alpar@397
    62
    
klao@946
    63
    class Node {
marci@975
    64
      friend class ListGraphBase;
klao@946
    65
    protected:
alpar@395
    66
klao@946
    67
      int id;
klao@946
    68
      Node(int pid) { id = pid;}
alpar@395
    69
klao@946
    70
    public:
klao@946
    71
      Node() {}
klao@946
    72
      Node (Invalid) { id = -1; }
klao@946
    73
      bool operator==(const Node& node) const {return id == node.id;}
klao@946
    74
      bool operator!=(const Node& node) const {return id != node.id;}
klao@946
    75
      bool operator<(const Node& node) const {return id < node.id;}
klao@946
    76
    };
deba@782
    77
klao@946
    78
    class Edge {
marci@975
    79
      friend class ListGraphBase;
klao@946
    80
    protected:
deba@782
    81
klao@946
    82
      int id;
klao@946
    83
      Edge(int pid) { id = pid;}
alpar@395
    84
klao@946
    85
    public:
klao@946
    86
      Edge() {}
klao@946
    87
      Edge (Invalid) { id = -1; }
klao@946
    88
      bool operator==(const Edge& edge) const {return id == edge.id;}
klao@946
    89
      bool operator!=(const Edge& edge) const {return id != edge.id;}
klao@946
    90
      bool operator<(const Edge& edge) const {return id < edge.id;}
klao@946
    91
    };
klao@946
    92
klao@946
    93
klao@946
    94
klao@946
    95
    ListGraphBase()
deba@782
    96
      : nodes(), first_node(-1),
deba@782
    97
	first_free_node(-1), edges(), first_free_edge(-1) {}
deba@782
    98
alpar@395
    99
    
alpar@813
   100
    /// Maximum node ID.
alpar@813
   101
    
alpar@813
   102
    /// Maximum node ID.
alpar@813
   103
    ///\sa id(Node)
deba@1791
   104
    int maxNodeId() const { return nodes.size()-1; } 
klao@946
   105
alpar@813
   106
    /// Maximum edge ID.
alpar@813
   107
    
alpar@813
   108
    /// Maximum edge ID.
alpar@813
   109
    ///\sa id(Edge)
deba@1791
   110
    int maxEdgeId() const { return edges.size()-1; }
alpar@395
   111
alpar@986
   112
    Node source(Edge e) const { return edges[e.id].source; }
alpar@986
   113
    Node target(Edge e) const { return edges[e.id].target; }
alpar@395
   114
alpar@395
   115
klao@946
   116
    void first(Node& node) const { 
klao@946
   117
      node.id = first_node;
klao@946
   118
    }
klao@946
   119
klao@946
   120
    void next(Node& node) const {
klao@946
   121
      node.id = nodes[node.id].next;
klao@946
   122
    }
klao@946
   123
klao@946
   124
klao@946
   125
    void first(Edge& e) const { 
klao@946
   126
      int n;
klao@946
   127
      for(n = first_node; 
klao@946
   128
	  n!=-1 && nodes[n].first_in == -1; 
klao@946
   129
	  n = nodes[n].next);
klao@946
   130
      e.id = (n == -1) ? -1 : nodes[n].first_in;
klao@946
   131
    }
klao@946
   132
klao@946
   133
    void next(Edge& edge) const {
klao@946
   134
      if (edges[edge.id].next_in != -1) {
klao@946
   135
	edge.id = edges[edge.id].next_in;
klao@946
   136
      } else {
klao@946
   137
	int n;
alpar@986
   138
	for(n = nodes[edges[edge.id].target].next;
klao@946
   139
	  n!=-1 && nodes[n].first_in == -1; 
klao@946
   140
	  n = nodes[n].next);
klao@946
   141
	edge.id = (n == -1) ? -1 : nodes[n].first_in;
klao@946
   142
      }      
klao@946
   143
    }
klao@946
   144
klao@946
   145
    void firstOut(Edge &e, const Node& v) const {
klao@946
   146
      e.id = nodes[v.id].first_out;
klao@946
   147
    }
klao@946
   148
    void nextOut(Edge &e) const {
klao@946
   149
      e.id=edges[e.id].next_out;
klao@946
   150
    }
klao@946
   151
klao@946
   152
    void firstIn(Edge &e, const Node& v) const {
klao@946
   153
      e.id = nodes[v.id].first_in;
klao@946
   154
    }
klao@946
   155
    void nextIn(Edge &e) const {
klao@946
   156
      e.id=edges[e.id].next_in;
klao@946
   157
    }
klao@946
   158
alpar@813
   159
    
klao@946
   160
    static int id(Node v) { return v.id; }
klao@946
   161
    static int id(Edge e) { return e.id; }
alpar@395
   162
deba@1791
   163
    static Node nodeFromId(int id) { return Node(id);}
deba@1791
   164
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   165
alpar@397
   166
    /// Adds a new node to the graph.
alpar@397
   167
alpar@813
   168
    /// \warning It adds the new node to the front of the list.
alpar@397
   169
    /// (i.e. the lastly added node becomes the first.)
klao@946
   170
    Node addNode() {     
alpar@397
   171
      int n;
alpar@397
   172
      
klao@946
   173
      if(first_free_node==-1) {
klao@946
   174
	n = nodes.size();
klao@946
   175
	nodes.push_back(NodeT());
klao@946
   176
      } else {
alpar@397
   177
	n = first_free_node;
alpar@397
   178
	first_free_node = nodes[n].next;
alpar@397
   179
      }
alpar@397
   180
      
alpar@397
   181
      nodes[n].next = first_node;
alpar@397
   182
      if(first_node != -1) nodes[first_node].prev = n;
alpar@397
   183
      first_node = n;
alpar@397
   184
      nodes[n].prev = -1;
alpar@397
   185
      
alpar@397
   186
      nodes[n].first_in = nodes[n].first_out = -1;
alpar@397
   187
      
klao@946
   188
      return Node(n);
alpar@395
   189
    }
alpar@395
   190
    
alpar@395
   191
    Edge addEdge(Node u, Node v) {
klao@946
   192
      int n;      
klao@946
   193
klao@946
   194
      if (first_free_edge == -1) {
klao@946
   195
	n = edges.size();
klao@946
   196
	edges.push_back(EdgeT());
klao@946
   197
      } else {
alpar@397
   198
	n = first_free_edge;
alpar@397
   199
	first_free_edge = edges[n].next_in;
alpar@397
   200
      }
alpar@397
   201
      
alpar@986
   202
      edges[n].source = u.id; 
alpar@986
   203
      edges[n].target = v.id;
alpar@395
   204
klao@946
   205
      edges[n].next_out = nodes[u.id].first_out;
klao@946
   206
      if(nodes[u.id].first_out != -1) {
klao@946
   207
	edges[nodes[u.id].first_out].prev_out = n;
klao@946
   208
      }
klao@946
   209
      
klao@946
   210
      edges[n].next_in = nodes[v.id].first_in;
klao@946
   211
      if(nodes[v.id].first_in != -1) {
klao@946
   212
	edges[nodes[v.id].first_in].prev_in = n;
klao@946
   213
      }
klao@946
   214
      
alpar@397
   215
      edges[n].prev_in = edges[n].prev_out = -1;
alpar@397
   216
	
klao@946
   217
      nodes[u.id].first_out = nodes[v.id].first_in = n;
alpar@397
   218
klao@946
   219
      return Edge(n);
alpar@395
   220
    }
alpar@774
   221
    
klao@946
   222
    void erase(const Node& node) {
klao@946
   223
      int n = node.id;
klao@946
   224
      
klao@946
   225
      if(nodes[n].next != -1) {
klao@946
   226
	nodes[nodes[n].next].prev = nodes[n].prev;
klao@946
   227
      }
klao@946
   228
      
klao@946
   229
      if(nodes[n].prev != -1) {
klao@946
   230
	nodes[nodes[n].prev].next = nodes[n].next;
klao@946
   231
      } else {
klao@946
   232
	first_node = nodes[n].next;
klao@946
   233
      }
klao@946
   234
      
klao@946
   235
      nodes[n].next = first_free_node;
klao@946
   236
      first_free_node = n;
alpar@395
   237
alpar@774
   238
    }
alpar@774
   239
    
klao@946
   240
    void erase(const Edge& edge) {
klao@946
   241
      int n = edge.id;
alpar@397
   242
      
klao@946
   243
      if(edges[n].next_in!=-1) {
alpar@397
   244
	edges[edges[n].next_in].prev_in = edges[n].prev_in;
klao@946
   245
      }
klao@946
   246
klao@946
   247
      if(edges[n].prev_in!=-1) {
alpar@397
   248
	edges[edges[n].prev_in].next_in = edges[n].next_in;
klao@946
   249
      } else {
alpar@986
   250
	nodes[edges[n].target].first_in = edges[n].next_in;
klao@946
   251
      }
klao@946
   252
alpar@397
   253
      
klao@946
   254
      if(edges[n].next_out!=-1) {
alpar@397
   255
	edges[edges[n].next_out].prev_out = edges[n].prev_out;
klao@946
   256
      } 
klao@946
   257
klao@946
   258
      if(edges[n].prev_out!=-1) {
alpar@397
   259
	edges[edges[n].prev_out].next_out = edges[n].next_out;
klao@946
   260
      } else {
alpar@986
   261
	nodes[edges[n].source].first_out = edges[n].next_out;
klao@946
   262
      }
alpar@397
   263
      
alpar@397
   264
      edges[n].next_in = first_free_edge;
alpar@695
   265
      first_free_edge = n;      
alpar@397
   266
alpar@397
   267
    }
alpar@397
   268
alpar@397
   269
    void clear() {
deba@782
   270
      edges.clear();
deba@782
   271
      nodes.clear();
klao@946
   272
      first_node = first_free_node = first_free_edge = -1;
deba@937
   273
    }
deba@937
   274
alpar@949
   275
  protected:
alpar@1546
   276
    void _changeTarget(Edge e, Node n) 
alpar@949
   277
    {
alpar@949
   278
      if(edges[e.id].next_in != -1)
alpar@949
   279
	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
alpar@949
   280
      if(edges[e.id].prev_in != -1)
alpar@949
   281
	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
alpar@986
   282
      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
deba@1702
   283
      if (nodes[n.id].first_in != -1) {
deba@1702
   284
	edges[nodes[n.id].first_in].prev_in = e.id;
deba@1702
   285
      }
alpar@986
   286
      edges[e.id].target = n.id;
alpar@949
   287
      edges[e.id].prev_in = -1;
alpar@949
   288
      edges[e.id].next_in = nodes[n.id].first_in;
alpar@949
   289
      nodes[n.id].first_in = e.id;
alpar@949
   290
    }
alpar@1546
   291
    void _changeSource(Edge e, Node n) 
alpar@949
   292
    {
alpar@949
   293
      if(edges[e.id].next_out != -1)
alpar@949
   294
	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
alpar@949
   295
      if(edges[e.id].prev_out != -1)
alpar@949
   296
	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
alpar@986
   297
      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
deba@1702
   298
      if (nodes[n.id].first_out != -1) {
deba@1702
   299
	edges[nodes[n.id].first_out].prev_out = e.id;
deba@1702
   300
      }
alpar@986
   301
      edges[e.id].source = n.id;
alpar@949
   302
      edges[e.id].prev_out = -1;
alpar@949
   303
      edges[e.id].next_out = nodes[n.id].first_out;
alpar@949
   304
      nodes[n.id].first_out = e.id;
alpar@949
   305
    }
alpar@949
   306
alpar@919
   307
  };
deba@909
   308
deba@1979
   309
  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
alpar@400
   310
deba@1718
   311
  /// \addtogroup graphs
deba@1718
   312
  /// @{
alpar@400
   313
alpar@948
   314
  ///A list graph class.
alpar@400
   315
alpar@948
   316
  ///This is a simple and fast erasable graph implementation.
alpar@948
   317
  ///
alpar@1010
   318
  ///It addition that it conforms to the
alpar@1010
   319
  ///\ref concept::ErasableGraph "ErasableGraph" concept,
alpar@1010
   320
  ///it also provides several additional useful extra functionalities.
klao@959
   321
  ///\sa concept::ErasableGraph.
deba@782
   322
deba@1669
   323
  class ListGraph : public ExtendedListGraphBase 
alpar@948
   324
  {
alpar@948
   325
  public:
alpar@1546
   326
    /// Changes the target of \c e to \c n
alpar@948
   327
alpar@1546
   328
    /// Changes the target of \c e to \c n
alpar@948
   329
    ///
alpar@1010
   330
    ///\note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
alpar@1546
   331
    ///referencing the changed edge remain
alpar@1010
   332
    ///valid. However <tt>InEdge</tt>'s are invalidated.
deba@1718
   333
    void changeTarget(Edge e, Node n) { 
deba@1718
   334
      _changeTarget(e,n); 
deba@1718
   335
    }
alpar@1546
   336
    /// Changes the source of \c e to \c n
alpar@948
   337
alpar@1546
   338
    /// Changes the source of \c e to \c n
alpar@948
   339
    ///
alpar@1010
   340
    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
alpar@1546
   341
    ///referencing the changed edge remain
alpar@1010
   342
    ///valid. However <tt>OutEdge</tt>'s are invalidated.
deba@1718
   343
    void changeSource(Edge e, Node n) { 
deba@1718
   344
      _changeSource(e,n);
deba@1718
   345
    }
alpar@949
   346
alpar@1010
   347
    /// Invert the direction of an edge.
alpar@1010
   348
alpar@1010
   349
    ///\note The <tt>Edge</tt>'s
alpar@1546
   350
    ///referencing the changed edge remain
alpar@1010
   351
    ///valid. However <tt>OutEdge</tt>'s  and <tt>InEdge</tt>'s are invalidated.
alpar@1010
   352
    void reverseEdge(Edge e) {
alpar@1010
   353
      Node t=target(e);
alpar@1546
   354
      _changeTarget(e,source(e));
alpar@1546
   355
      _changeSource(e,t);
alpar@1010
   356
    }
alpar@1010
   357
alpar@1010
   358
    ///Using this it possible to avoid the superfluous memory allocation.
alpar@1010
   359
alpar@949
   360
    ///Using this it possible to avoid the superfluous memory allocation.
alpar@949
   361
    ///\todo more docs...
alpar@949
   362
    void reserveEdge(int n) { edges.reserve(n); };
alpar@1010
   363
alpar@1010
   364
    ///Contract two nodes.
alpar@1010
   365
alpar@1010
   366
    ///This function contracts two nodes.
alpar@1010
   367
    ///
alpar@1010
   368
    ///Node \p b will be removed but instead of deleting
alpar@1010
   369
    ///its neighboring edges, they will be joined to \p a.
alpar@1010
   370
    ///The last parameter \p r controls whether to remove loops. \c true
alpar@1010
   371
    ///means that loops will be removed.
alpar@1010
   372
    ///
alpar@1010
   373
    ///\note The <tt>Edge</tt>s
alpar@1281
   374
    ///referencing a moved edge remain
alpar@1010
   375
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1010
   376
    ///may be invalidated.
deba@1718
   377
    void contract(Node a, Node b, bool r = true) 
alpar@1010
   378
    {
alpar@1010
   379
      for(OutEdgeIt e(*this,b);e!=INVALID;) {
alpar@1010
   380
	OutEdgeIt f=e;
alpar@1010
   381
	++f;
alpar@1010
   382
	if(r && target(e)==a) erase(e);
alpar@1546
   383
	else changeSource(e,a);
alpar@1010
   384
	e=f;
alpar@1010
   385
      }
alpar@1010
   386
      for(InEdgeIt e(*this,b);e!=INVALID;) {
alpar@1010
   387
	InEdgeIt f=e;
alpar@1010
   388
	++f;
alpar@1010
   389
	if(r && source(e)==a) erase(e);
alpar@1546
   390
	else changeTarget(e,a);
alpar@1010
   391
	e=f;
alpar@1010
   392
      }
alpar@1010
   393
      erase(b);
alpar@1010
   394
    }
alpar@1011
   395
alpar@1281
   396
    ///Split a node.
alpar@1011
   397
alpar@1284
   398
    ///This function splits a node. First a new node is added to the graph,
alpar@1284
   399
    ///then the source of each outgoing edge of \c n is moved to this new node.
alpar@1281
   400
    ///If \c connect is \c true (this is the default value), then a new edge
alpar@1281
   401
    ///from \c n to the newly created node is also added.
alpar@1281
   402
    ///\return The newly created node.
alpar@1281
   403
    ///
alpar@1281
   404
    ///\note The <tt>Edge</tt>s
alpar@1281
   405
    ///referencing a moved edge remain
alpar@1281
   406
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1281
   407
    ///may be invalidated.
alpar@1770
   408
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1284
   409
    ///feature.
alpar@1281
   410
    ///\todo It could be implemented in a bit faster way.
alpar@1281
   411
    Node split(Node n, bool connect = true) 
alpar@1281
   412
    {
alpar@1281
   413
      Node b = addNode();
alpar@1281
   414
      for(OutEdgeIt e(*this,n);e!=INVALID;) {
alpar@1281
   415
 	OutEdgeIt f=e;
alpar@1281
   416
	++f;
alpar@1546
   417
	changeSource(e,b);
alpar@1281
   418
	e=f;
alpar@1281
   419
      }
alpar@1281
   420
      if(connect) addEdge(n,b);
alpar@1281
   421
      return b;
alpar@1281
   422
    }
alpar@1281
   423
      
alpar@1812
   424
    ///Split an edge.
alpar@1812
   425
alpar@1812
   426
    ///This function splits an edge. First a new node \c b is added to the graph,
alpar@1812
   427
    ///then the original edge is re-targetes to \c b. Finally an edge
alpar@1812
   428
    ///from \c b to the original target is added.
alpar@1812
   429
    ///\return The newly created node.
alpar@1812
   430
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1812
   431
    ///feature.
alpar@1812
   432
    Node split(Edge e) 
alpar@1812
   433
    {
alpar@1812
   434
      Node b = addNode();
alpar@1812
   435
      addEdge(b,target(e));
alpar@1812
   436
      changeTarget(e,b);
alpar@1812
   437
      return b;
alpar@1812
   438
    }
alpar@1812
   439
      
alpar@1011
   440
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   441
alpar@1011
   442
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   443
    ///
alpar@1011
   444
    ///The newly added nodes and edges can be removed using the
alpar@1011
   445
    ///restore() function.
alpar@1011
   446
    ///
alpar@1011
   447
    ///\warning Edge and node deletions cannot be restored.
alpar@1770
   448
    ///\warning Snapshots cannot be nested.
alpar@1770
   449
    class Snapshot : protected AlterationNotifier<Node>::ObserverBase,
deba@1039
   450
		     protected AlterationNotifier<Edge>::ObserverBase
alpar@1011
   451
    {
deba@1774
   452
    public:
deba@1774
   453
      
deba@1774
   454
      class UnsupportedOperation : public LogicError {
deba@1774
   455
      public:
deba@1774
   456
	virtual const char* exceptionName() const {
deba@1774
   457
	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
deba@1774
   458
	}
deba@1774
   459
      };
deba@1774
   460
            
deba@1774
   461
alpar@1011
   462
      protected:
alpar@1011
   463
      
alpar@1011
   464
      ListGraph *g;
alpar@1011
   465
      std::list<Node> added_nodes;
alpar@1011
   466
      std::list<Edge> added_edges;
alpar@1011
   467
      
alpar@1011
   468
      bool active;
alpar@1011
   469
      virtual void add(const Node& n) {
alpar@1011
   470
	added_nodes.push_back(n);
alpar@1011
   471
      };
alpar@1011
   472
      virtual void erase(const Node&) 
alpar@1011
   473
      {
deba@1774
   474
	throw UnsupportedOperation();
alpar@1011
   475
      }
alpar@1011
   476
      virtual void add(const Edge& n) {
alpar@1011
   477
	added_edges.push_back(n);
alpar@1011
   478
      };
alpar@1011
   479
      virtual void erase(const Edge&) 
alpar@1011
   480
      {
deba@1774
   481
	throw UnsupportedOperation();
alpar@1011
   482
      }
alpar@1011
   483
alpar@1457
   484
      ///\bug What is this used for?
alpar@1457
   485
      ///
alpar@1457
   486
      virtual void build() {}
alpar@1457
   487
      ///\bug What is this used for?
alpar@1457
   488
      ///
alpar@1457
   489
      virtual void clear() {}
alpar@1457
   490
alpar@1011
   491
      void regist(ListGraph &_g) {
alpar@1011
   492
	g=&_g;
deba@1039
   493
	AlterationNotifier<Node>::ObserverBase::
deba@1040
   494
	  attach(g->getNotifier(Node()));
deba@1039
   495
	AlterationNotifier<Edge>::ObserverBase::
deba@1040
   496
	  attach(g->getNotifier(Edge()));
alpar@1011
   497
      }
alpar@1011
   498
            
alpar@1011
   499
      void deregist() {
deba@1039
   500
	AlterationNotifier<Node>::ObserverBase::
alpar@1011
   501
	  detach();
deba@1039
   502
	AlterationNotifier<Edge>::ObserverBase::
alpar@1011
   503
	  detach();
alpar@1011
   504
	g=0;
alpar@1011
   505
      }
deba@1774
   506
alpar@1011
   507
    public:
alpar@1011
   508
      ///Default constructur.
alpar@1011
   509
      
alpar@1011
   510
      ///Default constructur.
alpar@1011
   511
      ///To actually make a snapshot you must call save().
alpar@1011
   512
      ///
alpar@1770
   513
      Snapshot() : g(0) {}
alpar@1011
   514
      ///Constructor that immediately makes a snapshot.
alpar@1011
   515
      
alpar@1011
   516
      ///This constructor immediately makes a snapshot of the graph.
alpar@1011
   517
      ///\param _g The graph we make a snapshot of.
alpar@1770
   518
      Snapshot(ListGraph &_g) {
alpar@1011
   519
	regist(_g);
alpar@1011
   520
      }
alpar@1011
   521
      ///\bug Is it necessary?
alpar@1011
   522
      ///
alpar@1770
   523
      ~Snapshot() 
alpar@1011
   524
      {
alpar@1011
   525
	if(g) deregist();
alpar@1011
   526
      }
alpar@1011
   527
      
alpar@1011
   528
      ///Make a snapshot.
alpar@1011
   529
alpar@1011
   530
      ///Make a snapshot of the graph.
alpar@1011
   531
      ///
alpar@1011
   532
      ///This function can be called more than once. In case of a repeated
alpar@1011
   533
      ///call, the previous snapshot gets lost.
alpar@1011
   534
      ///\param _g The graph we make the snapshot of.
alpar@1011
   535
      void save(ListGraph &_g) 
alpar@1011
   536
      {
alpar@1011
   537
	if(g!=&_g) {
alpar@1011
   538
	  if(g) deregist();
alpar@1011
   539
	  regist(_g);
alpar@1011
   540
	}
alpar@1011
   541
	added_nodes.clear();
alpar@1011
   542
	added_edges.clear();
alpar@1011
   543
      }
alpar@1011
   544
      
alpar@1011
   545
    ///Undo the changes until the last snapshot.
alpar@1011
   546
alpar@1011
   547
    ///Undo the changes until last snapshot created by save().
alpar@1011
   548
    ///
alpar@1011
   549
    ///\todo This function might be called undo().
alpar@1011
   550
      void restore() {
alpar@1457
   551
	ListGraph &old_g=*g;
alpar@1011
   552
	deregist();
alpar@1011
   553
	while(!added_edges.empty()) {
alpar@1457
   554
	  old_g.erase(added_edges.front());
alpar@1011
   555
	  added_edges.pop_front();
alpar@1011
   556
	}
alpar@1011
   557
 	while(!added_nodes.empty()) {
alpar@1457
   558
	  old_g.erase(added_nodes.front());
alpar@1011
   559
	  added_nodes.pop_front();
alpar@1011
   560
	}
alpar@1011
   561
      }
alpar@1011
   562
    };
alpar@1011
   563
    
alpar@949
   564
  };
klao@1034
   565
alpar@1555
   566
  ///@}
klao@1034
   567
klao@1034
   568
  /**************** Undirected List Graph ****************/
klao@1034
   569
deba@1979
   570
  typedef UGraphExtender<UGraphBaseExtender<
deba@1979
   571
    ListGraphBase> > ExtendedListUGraphBase;
klao@1034
   572
deba@1718
   573
  /// \addtogroup graphs
deba@1718
   574
  /// @{
alpar@1555
   575
alpar@1035
   576
  ///An undirected list graph class.
alpar@1035
   577
alpar@1035
   578
  ///This is a simple and fast erasable undirected graph implementation.
alpar@1035
   579
  ///
alpar@1035
   580
  ///It conforms to the
klao@1909
   581
  ///\ref concept::UGraph "UGraph" concept.
alpar@1035
   582
  ///
klao@1909
   583
  ///\sa concept::UGraph.
alpar@1035
   584
  ///
alpar@1770
   585
  ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
alpar@1161
   586
  ///haven't been implemented yet.
alpar@1035
   587
  ///
klao@1909
   588
  class ListUGraph : public ExtendedListUGraphBase {
deba@1718
   589
  public:
klao@1909
   590
    typedef ExtendedListUGraphBase Parent;
deba@1718
   591
    /// \brief Changes the target of \c e to \c n
deba@1718
   592
    ///
deba@1718
   593
    /// Changes the target of \c e to \c n
deba@1718
   594
    ///
deba@1718
   595
    /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
deba@1718
   596
    /// referencing the changed edge remain
deba@1718
   597
    /// valid. However <tt>InEdge</tt>'s are invalidated.
klao@1909
   598
    void changeTarget(UEdge e, Node n) { 
deba@1718
   599
      _changeTarget(e,n); 
deba@1718
   600
    }
deba@1718
   601
    /// Changes the source of \c e to \c n
deba@1718
   602
    ///
deba@1718
   603
    /// Changes the source of \c e to \c n
deba@1718
   604
    ///
deba@1718
   605
    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
deba@1718
   606
    ///referencing the changed edge remain
deba@1718
   607
    ///valid. However <tt>OutEdge</tt>'s are invalidated.
klao@1909
   608
    void changeSource(UEdge e, Node n) { 
deba@1718
   609
      _changeSource(e,n); 
deba@1718
   610
    }
deba@1718
   611
    /// \brief Contract two nodes.
deba@1718
   612
    ///
deba@1718
   613
    /// This function contracts two nodes.
deba@1718
   614
    ///
deba@1718
   615
    /// Node \p b will be removed but instead of deleting
deba@1718
   616
    /// its neighboring edges, they will be joined to \p a.
deba@1718
   617
    /// The last parameter \p r controls whether to remove loops. \c true
deba@1718
   618
    /// means that loops will be removed.
deba@1718
   619
    ///
deba@1718
   620
    /// \note The <tt>Edge</tt>s
deba@1718
   621
    /// referencing a moved edge remain
deba@1718
   622
    /// valid.
deba@1718
   623
    void contract(Node a, Node b, bool r = true) {
deba@1718
   624
      for(IncEdgeIt e(*this, b); e!=INVALID;) {
deba@1718
   625
	IncEdgeIt f = e; ++f;
deba@1718
   626
	if (r && runningNode(e) == a) {
deba@1718
   627
	  erase(e);
deba@1718
   628
	} else if (source(e) == b) {
deba@1718
   629
	  changeSource(e, a);
deba@1718
   630
	} else {
deba@1718
   631
	  changeTarget(e, a);
deba@1718
   632
	}
deba@1718
   633
	e = f;
deba@1718
   634
      }
deba@1718
   635
      erase(b);
deba@1718
   636
    }
klao@1034
   637
  };
klao@1034
   638
deba@1982
   639
deba@1982
   640
  class ListBpUGraphBase {
deba@1982
   641
  public:
deba@1982
   642
deba@1982
   643
    class NodeSetError : public LogicError {
deba@1982
   644
      virtual const char* exceptionName() const { 
deba@1982
   645
	return "lemon::ListBpUGraph::NodeSetError";
deba@1982
   646
      }
deba@1982
   647
    };
deba@1982
   648
deba@1982
   649
  protected:
deba@1982
   650
deba@1982
   651
    struct NodeT {
deba@1982
   652
      int first_edge, next_node;
deba@1982
   653
    };
deba@1982
   654
deba@1982
   655
    struct EdgeT {
deba@1982
   656
      int aNode, prev_out, next_out;
deba@1982
   657
      int bNode, prev_in, next_in;
deba@1982
   658
    };
deba@1982
   659
deba@1982
   660
    std::vector<NodeT> aNodes;
deba@1982
   661
    std::vector<NodeT> bNodes;
deba@1982
   662
deba@1982
   663
    std::vector<EdgeT> edges;
deba@1982
   664
deba@1982
   665
    int first_anode;
deba@1982
   666
    int first_free_anode;
deba@1982
   667
deba@1982
   668
    int first_bnode;
deba@1982
   669
    int first_free_bnode;
deba@1982
   670
deba@1982
   671
    int first_free_edge;
deba@1982
   672
deba@1982
   673
  public:
deba@1982
   674
  
deba@1982
   675
    class Node {
deba@1982
   676
      friend class ListBpUGraphBase;
deba@1982
   677
    protected:
deba@1982
   678
      int id;
deba@1982
   679
deba@1982
   680
      Node(int _id) : id(_id) {}
deba@1982
   681
    public:
deba@1982
   682
      Node() {}
deba@1982
   683
      Node(Invalid) { id = -1; }
deba@1982
   684
      bool operator==(const Node i) const {return id==i.id;}
deba@1982
   685
      bool operator!=(const Node i) const {return id!=i.id;}
deba@1982
   686
      bool operator<(const Node i) const {return id<i.id;}
deba@1982
   687
    };
deba@1982
   688
deba@1982
   689
    class Edge {
deba@1982
   690
      friend class ListBpUGraphBase;
deba@1982
   691
    protected:
deba@1982
   692
      int id;
deba@1982
   693
deba@1982
   694
      Edge(int _id) { id = _id;}
deba@1982
   695
    public:
deba@1982
   696
      Edge() {}
deba@1982
   697
      Edge (Invalid) { id = -1; }
deba@1982
   698
      bool operator==(const Edge i) const {return id==i.id;}
deba@1982
   699
      bool operator!=(const Edge i) const {return id!=i.id;}
deba@1982
   700
      bool operator<(const Edge i) const {return id<i.id;}
deba@1982
   701
    };
deba@1982
   702
deba@1982
   703
    ListBpUGraphBase()
deba@1982
   704
      : first_anode(-1), first_free_anode(-1),
deba@1982
   705
        first_bnode(-1), first_free_bnode(-1),
deba@1982
   706
        first_free_edge(-1) {}
deba@1982
   707
deba@1982
   708
    void firstANode(Node& node) const {
deba@1982
   709
      node.id = first_anode != -1 ? (first_anode << 1) : -1;
deba@1982
   710
    }
deba@1982
   711
    void nextANode(Node& node) const {
deba@1982
   712
      node.id = aNodes[node.id >> 1].next_node;
deba@1982
   713
    }
deba@1982
   714
deba@1982
   715
    void firstBNode(Node& node) const {
deba@1982
   716
      node.id =  first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
deba@1982
   717
    }
deba@1982
   718
    void nextBNode(Node& node) const {
deba@1984
   719
      node.id = bNodes[node.id >> 1].next_node;
deba@1982
   720
    }
deba@1982
   721
deba@1982
   722
    void first(Node& node) const {
deba@1982
   723
      if (first_anode != -1) {
deba@1982
   724
        node.id = (first_anode << 1);
deba@1982
   725
      } else if (first_bnode != -1) {
deba@1982
   726
        node.id = (first_bnode << 1) + 1;
deba@1982
   727
      } else {
deba@1982
   728
        node.id = -1;
deba@1982
   729
      }
deba@1982
   730
    }
deba@1982
   731
    void next(Node& node) const {
deba@1982
   732
      if (aNode(node)) {
deba@1982
   733
        node.id = aNodes[node.id >> 1].next_node;
deba@1982
   734
        if (node.id == -1) {
deba@1982
   735
          if (first_bnode != -1) {
deba@1982
   736
            node.id = (first_bnode << 1) + 1;
deba@1982
   737
          }
deba@1982
   738
        }
deba@1982
   739
      } else {
deba@1982
   740
        node.id = bNodes[node.id >> 1].next_node;
deba@1982
   741
      }
deba@1982
   742
    }
deba@1982
   743
  
deba@1982
   744
    void first(Edge& edge) const {
deba@1982
   745
      int aNodeId = first_anode;
deba@1982
   746
      while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
deba@1982
   747
        aNodeId = aNodes[aNodeId].next_node != -1 ? 
deba@1982
   748
          aNodes[aNodeId].next_node >> 1 : -1;
deba@1982
   749
      }
deba@1982
   750
      if (aNodeId != -1) {
deba@1982
   751
        edge.id = aNodes[aNodeId].first_edge;
deba@1982
   752
      } else {
deba@1982
   753
        edge.id = -1;
deba@1982
   754
      }
deba@1982
   755
    }
deba@1982
   756
    void next(Edge& edge) const {
deba@1982
   757
      int aNodeId = edges[edge.id].aNode >> 1;
deba@1982
   758
      edge.id = edges[edge.id].next_out;
deba@1982
   759
      if (edge.id == -1) {
deba@1982
   760
        aNodeId = aNodes[aNodeId].next_node != -1 ? 
deba@1982
   761
          aNodes[aNodeId].next_node >> 1 : -1;
deba@1982
   762
        while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
deba@1982
   763
          aNodeId = aNodes[aNodeId].next_node != -1 ? 
deba@1982
   764
          aNodes[aNodeId].next_node >> 1 : -1;
deba@1982
   765
        }
deba@1982
   766
        if (aNodeId != -1) {
deba@1982
   767
          edge.id = aNodes[aNodeId].first_edge;
deba@1982
   768
        } else {
deba@1982
   769
          edge.id = -1;
deba@1982
   770
        }
deba@1982
   771
      }
deba@1982
   772
    }
deba@1982
   773
deba@1982
   774
    void firstOut(Edge& edge, const Node& node) const {
deba@1982
   775
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@1982
   776
      edge.id = aNodes[node.id >> 1].first_edge;
deba@1982
   777
    }
deba@1982
   778
    void nextOut(Edge& edge) const {
deba@1982
   779
      edge.id = edges[edge.id].next_out;
deba@1982
   780
    }
deba@1982
   781
deba@1982
   782
    void firstIn(Edge& edge, const Node& node) const {
deba@1982
   783
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@1982
   784
      edge.id = bNodes[node.id >> 1].first_edge;
deba@1982
   785
    }
deba@1982
   786
    void nextIn(Edge& edge) const {
deba@1982
   787
      edge.id = edges[edge.id].next_in;
deba@1982
   788
    }
deba@1982
   789
deba@1982
   790
    static int id(const Node& node) {
deba@1982
   791
      return node.id;
deba@1982
   792
    }
deba@1982
   793
    static Node nodeFromId(int id) {
deba@1982
   794
      return Node(id);
deba@1982
   795
    }
deba@1982
   796
    int maxNodeId() const {
deba@1982
   797
      return aNodes.size() > bNodes.size() ?
deba@1982
   798
	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
deba@1982
   799
    }
deba@1982
   800
  
deba@1982
   801
    static int id(const Edge& edge) {
deba@1982
   802
      return edge.id;
deba@1982
   803
    }
deba@1982
   804
    static Edge edgeFromId(int id) {
deba@1982
   805
      return Edge(id);
deba@1982
   806
    }
deba@1982
   807
    int maxEdgeId() const {
deba@1982
   808
      return edges.size();
deba@1982
   809
    }
deba@1982
   810
  
deba@1982
   811
    static int aNodeId(const Node& node) {
deba@1982
   812
      return node.id >> 1;
deba@1982
   813
    }
deba@1982
   814
    static Node fromANodeId(int id, Node) {
deba@1982
   815
      return Node(id << 1);
deba@1982
   816
    }
deba@1982
   817
    int maxANodeId() const {
deba@1982
   818
      return aNodes.size();
deba@1982
   819
    }
deba@1982
   820
deba@1982
   821
    static int bNodeId(const Node& node) {
deba@1982
   822
      return node.id >> 1;
deba@1982
   823
    }
deba@1982
   824
    static Node fromBNodeId(int id) {
deba@1982
   825
      return Node((id << 1) + 1);
deba@1982
   826
    }
deba@1982
   827
    int maxBNodeId() const {
deba@1982
   828
      return bNodes.size();
deba@1982
   829
    }
deba@1982
   830
deba@1982
   831
    Node aNode(const Edge& edge) const {
deba@1982
   832
      return Node(edges[edge.id].aNode);
deba@1982
   833
    }
deba@1982
   834
    Node bNode(const Edge& edge) const {
deba@1982
   835
      return Node(edges[edge.id].bNode);
deba@1982
   836
    }
deba@1982
   837
deba@1982
   838
    static bool aNode(const Node& node) {
deba@1982
   839
      return (node.id & 1) == 0;
deba@1982
   840
    }
deba@1982
   841
deba@1982
   842
    static bool bNode(const Node& node) {
deba@1982
   843
      return (node.id & 1) == 1;
deba@1982
   844
    }
deba@1982
   845
deba@1982
   846
    Node addANode() {
deba@1982
   847
      int aNodeId;
deba@1982
   848
      if (first_free_anode == -1) {
deba@1982
   849
        aNodeId = aNodes.size();
deba@1982
   850
        aNodes.push_back(NodeT());
deba@1982
   851
      } else {
deba@1982
   852
        aNodeId = first_free_anode;
deba@1982
   853
        first_free_anode = aNodes[first_free_anode].next_node;
deba@1982
   854
      }
deba@1982
   855
      aNodes[aNodeId].next_node = 
deba@1982
   856
        first_anode != -1 ? (first_anode << 1) : -1;
deba@1982
   857
      first_anode = aNodeId;
deba@1982
   858
      aNodes[aNodeId].first_edge = -1;
deba@1982
   859
      return Node(aNodeId << 1);
deba@1982
   860
    }
deba@1982
   861
deba@1982
   862
    Node addBNode() {
deba@1982
   863
      int bNodeId;
deba@1984
   864
      if (first_free_bnode == -1) {
deba@1982
   865
        bNodeId = bNodes.size();
deba@1982
   866
        bNodes.push_back(NodeT());
deba@1982
   867
      } else {
deba@1982
   868
        bNodeId = first_free_bnode;
deba@1982
   869
        first_free_bnode = bNodes[first_free_bnode].next_node;
deba@1982
   870
      }
deba@1982
   871
      bNodes[bNodeId].next_node = 
deba@1982
   872
        first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
deba@1982
   873
      first_bnode = bNodeId;
deba@1982
   874
      bNodes[bNodeId].first_edge = -1;
deba@1982
   875
      return Node((bNodeId << 1) + 1);
deba@1982
   876
    }
deba@1982
   877
deba@1982
   878
    Edge addEdge(const Node& source, const Node& target) {
deba@1982
   879
      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
deba@1982
   880
      int edgeId;
deba@1982
   881
      if (first_free_edge != -1) {
deba@1982
   882
        edgeId = first_free_edge;
deba@1982
   883
        first_free_edge = edges[edgeId].next_out;
deba@1982
   884
      } else {
deba@1982
   885
        edgeId = edges.size();
deba@1982
   886
        edges.push_back(EdgeT());
deba@1982
   887
      }
deba@1982
   888
      if ((source.id & 1) == 0) {
deba@1982
   889
	edges[edgeId].aNode = source.id;
deba@1982
   890
	edges[edgeId].bNode = target.id;
deba@1982
   891
      } else {
deba@1982
   892
	edges[edgeId].aNode = target.id;
deba@1982
   893
	edges[edgeId].bNode = source.id;
deba@1982
   894
      }
deba@1982
   895
      edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
deba@1982
   896
      edges[edgeId].prev_out = -1;
deba@1982
   897
      if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
deba@1982
   898
        edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
deba@1982
   899
      }
deba@1982
   900
      aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
deba@1982
   901
      edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
deba@1982
   902
      edges[edgeId].prev_in = -1;
deba@1982
   903
      if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
deba@1982
   904
        edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
deba@1982
   905
      }
deba@1982
   906
      bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
deba@1982
   907
      return Edge(edgeId);
deba@1982
   908
    }
deba@1982
   909
deba@1982
   910
    void erase(const Node& node) {
deba@1982
   911
      if (aNode(node)) {
deba@1982
   912
        int aNodeId = node.id >> 1;
deba@1982
   913
        aNodes[aNodeId].next_node = first_free_anode;
deba@1982
   914
        first_free_anode = aNodeId;
deba@1982
   915
      } else {
deba@1982
   916
        int bNodeId = node.id >> 1;
deba@1982
   917
        bNodes[bNodeId].next_node = first_free_bnode;
deba@1982
   918
        first_free_bnode = bNodeId;
deba@1982
   919
      }
deba@1982
   920
    }
deba@1982
   921
deba@1982
   922
    void erase(const Edge& edge) {
deba@1982
   923
      if (edges[edge.id].prev_out != -1) {
deba@1982
   924
        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
deba@1982
   925
      } else {
deba@1982
   926
        aNodes[edges[edge.id].aNode].first_edge = edges[edge.id].next_out;
deba@1982
   927
      }
deba@1982
   928
      if (edges[edge.id].next_out != -1) {
deba@1982
   929
        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
deba@1982
   930
      }
deba@1982
   931
      if (edges[edge.id].prev_in != -1) {
deba@1982
   932
        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
deba@1982
   933
      } else {
deba@1982
   934
        bNodes[edges[edge.id].bNode].first_edge = edges[edge.id].next_in;
deba@1982
   935
      }
deba@1982
   936
      if (edges[edge.id].next_in != -1) {
deba@1982
   937
        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
deba@1982
   938
      }
deba@1982
   939
      edges[edge.id].next_out = first_free_edge;
deba@1982
   940
      first_free_edge = edge.id;
deba@1982
   941
    }
deba@1982
   942
deba@1982
   943
    void clear() {
deba@1982
   944
      aNodes.clear();
deba@1982
   945
      bNodes.clear();
deba@1982
   946
      edges.clear();
deba@1982
   947
      first_anode = -1;
deba@1982
   948
      first_free_anode = -1;
deba@1982
   949
      first_bnode = -1;
deba@1982
   950
      first_free_bnode = -1;
deba@1982
   951
      first_free_edge = -1;
deba@1982
   952
    }
deba@1982
   953
deba@1982
   954
  };
deba@1982
   955
deba@1982
   956
deba@1982
   957
  typedef BpUGraphExtender< BpUGraphBaseExtender<
deba@1982
   958
    ListBpUGraphBase> > ExtendedListBpUGraphBase;
deba@1982
   959
deba@1982
   960
  /// \ingroup graphs
deba@1982
   961
  ///
deba@1982
   962
  /// \brief A smart bipartite undirected graph class.
deba@1982
   963
  ///
deba@1982
   964
  /// This is a bipartite undirected graph implementation.
deba@1991
   965
  /// It is conforms to the \ref concept::ErasableBpUGraph "ErasableBpUGraph" 
deba@1991
   966
  /// concept.
deba@1982
   967
  /// \sa concept::BpUGraph.
deba@1982
   968
  ///
deba@1982
   969
  class ListBpUGraph : public ExtendedListBpUGraphBase {};
deba@1982
   970
alpar@949
   971
  
alpar@948
   972
  /// @}  
alpar@948
   973
} //namespace lemon
klao@946
   974
  
alpar@400
   975
klao@946
   976
#endif