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