lemon/smart_graph.h
author deba
Mon, 03 Apr 2006 09:45:23 +0000
changeset 2031 080d51024ac5
parent 1999 2ff283124dfc
child 2076 10681ee9d8ae
permissions -rw-r--r--
Correcting the structure of the graph's and adaptor's map.
The template assign operators and map iterators can be used for adaptors also.

Some bugfix in the adaptors

New class SwapBpUGraphAdaptor which swaps the two nodeset of the graph.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     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@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@105
    18
alpar@921
    19
#ifndef LEMON_SMART_GRAPH_H
alpar@921
    20
#define LEMON_SMART_GRAPH_H
alpar@104
    21
klao@491
    22
///\ingroup graphs
alpar@242
    23
///\file
klao@1909
    24
///\brief SmartGraph and SmartUGraph classes.
alpar@242
    25
alpar@104
    26
#include <vector>
alpar@104
    27
deba@1993
    28
#include <lemon/bits/invalid.h>
alpar@157
    29
deba@1999
    30
#include <lemon/bits/base_extender.h>
deba@1791
    31
#include <lemon/bits/graph_extender.h>
klao@1034
    32
deba@1993
    33
#include <lemon/bits/utility.h>
deba@1820
    34
#include <lemon/error.h>
deba@782
    35
deba@1979
    36
#include <lemon/bits/graph_extender.h>
deba@1979
    37
alpar@921
    38
namespace lemon {
alpar@104
    39
alpar@973
    40
  class SmartGraph;
alpar@969
    41
  ///Base of SmartGraph
alpar@969
    42
alpar@969
    43
  ///Base of SmartGraph
alpar@969
    44
  ///
klao@946
    45
  class SmartGraphBase {
alpar@104
    46
alpar@973
    47
    friend class SmatGraph;
alpar@973
    48
alpar@973
    49
  protected:
alpar@104
    50
    struct NodeT 
alpar@104
    51
    {
alpar@104
    52
      int first_in,first_out;      
alpar@157
    53
      NodeT() : first_in(-1), first_out(-1) {}
alpar@104
    54
    };
alpar@104
    55
    struct EdgeT 
alpar@104
    56
    {
alpar@986
    57
      int target, source, next_in, next_out;      
alpar@104
    58
      //FIXME: is this necessary?
alpar@157
    59
      EdgeT() : next_in(-1), next_out(-1) {}  
alpar@104
    60
    };
alpar@104
    61
alpar@104
    62
    std::vector<NodeT> nodes;
alpar@129
    63
alpar@104
    64
    std::vector<EdgeT> edges;
alpar@104
    65
    
alpar@185
    66
    
alpar@104
    67
  public:
deba@782
    68
klao@946
    69
    typedef SmartGraphBase Graph;
alpar@104
    70
alpar@164
    71
    class Node;
alpar@164
    72
    class Edge;
alpar@108
    73
alpar@104
    74
    
alpar@104
    75
  public:
alpar@104
    76
klao@946
    77
    SmartGraphBase() : nodes(), edges() { }
deba@1718
    78
    SmartGraphBase(const SmartGraphBase &_g) 
deba@1718
    79
      : nodes(_g.nodes), edges(_g.edges) { }
alpar@104
    80
    
klao@977
    81
    typedef True NodeNumTag;
klao@977
    82
    typedef True EdgeNumTag;
klao@977
    83
alpar@813
    84
    ///Number of nodes.
alpar@813
    85
    int nodeNum() const { return nodes.size(); }
alpar@813
    86
    ///Number of edges.
alpar@813
    87
    int edgeNum() const { return edges.size(); }
alpar@104
    88
alpar@813
    89
    /// Maximum node ID.
alpar@813
    90
    
alpar@813
    91
    /// Maximum node ID.
alpar@813
    92
    ///\sa id(Node)
deba@1791
    93
    int maxNodeId() const { return nodes.size()-1; }
alpar@813
    94
    /// Maximum edge ID.
alpar@813
    95
    
alpar@813
    96
    /// Maximum edge ID.
alpar@813
    97
    ///\sa id(Edge)
deba@1791
    98
    int maxEdgeId() const { return edges.size()-1; }
alpar@108
    99
alpar@986
   100
    Node source(Edge e) const { return edges[e.n].source; }
alpar@986
   101
    Node target(Edge e) const { return edges[e.n].target; }
alpar@104
   102
alpar@813
   103
    /// Node ID.
alpar@813
   104
    
alpar@813
   105
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@1791
   106
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@1791
   107
    /// and the greatest node ID can be actually less then \ref maxNodeId().
alpar@813
   108
    ///
alpar@813
   109
    /// The ID of the \ref INVALID node is -1.
alpar@813
   110
    ///\return The ID of the node \c v. 
alpar@713
   111
    static int id(Node v) { return v.n; }
alpar@813
   112
    /// Edge ID.
alpar@813
   113
    
alpar@813
   114
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@1791
   115
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@1791
   116
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
alpar@813
   117
    ///
alpar@813
   118
    /// The ID of the \ref INVALID edge is -1.
alpar@813
   119
    ///\return The ID of the edge \c e. 
alpar@713
   120
    static int id(Edge e) { return e.n; }
alpar@104
   121
deba@1791
   122
    static Node nodeFromId(int id) { return Node(id);}
deba@1106
   123
deba@1791
   124
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   125
alpar@164
   126
    Node addNode() {
alpar@164
   127
      Node n; n.n=nodes.size();
alpar@104
   128
      nodes.push_back(NodeT()); //FIXME: Hmmm...
alpar@104
   129
      return n;
alpar@104
   130
    }
alpar@108
   131
    
alpar@164
   132
    Edge addEdge(Node u, Node v) {
alpar@164
   133
      Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
alpar@986
   134
      edges[e.n].source=u.n; edges[e.n].target=v.n;
alpar@104
   135
      edges[e.n].next_out=nodes[u.n].first_out;
alpar@104
   136
      edges[e.n].next_in=nodes[v.n].first_in;
alpar@104
   137
      nodes[u.n].first_out=nodes[v.n].first_in=e.n;
alpar@108
   138
alpar@104
   139
      return e;
alpar@104
   140
    }
alpar@104
   141
deba@782
   142
    void clear() {
deba@782
   143
      edges.clear();
deba@782
   144
      nodes.clear();
deba@782
   145
    }
alpar@104
   146
klao@946
   147
alpar@164
   148
    class Node {
klao@946
   149
      friend class SmartGraphBase;
alpar@973
   150
      friend class SmartGraph;
alpar@104
   151
alpar@104
   152
    protected:
alpar@104
   153
      int n;
alpar@164
   154
      Node(int nn) {n=nn;}
alpar@104
   155
    public:
alpar@164
   156
      Node() {}
alpar@503
   157
      Node (Invalid) { n=-1; }
alpar@164
   158
      bool operator==(const Node i) const {return n==i.n;}
alpar@164
   159
      bool operator!=(const Node i) const {return n!=i.n;}
alpar@164
   160
      bool operator<(const Node i) const {return n<i.n;}
alpar@104
   161
    };
alpar@104
   162
    
alpar@104
   163
alpar@164
   164
    class Edge {
klao@946
   165
      friend class SmartGraphBase;
alpar@973
   166
      friend class SmartGraph;
alpar@185
   167
alpar@104
   168
    protected:
alpar@104
   169
      int n;
alpar@905
   170
      Edge(int nn) {n=nn;}
alpar@706
   171
    public:
alpar@164
   172
      Edge() { }
marci@174
   173
      Edge (Invalid) { n=-1; }
alpar@164
   174
      bool operator==(const Edge i) const {return n==i.n;}
alpar@164
   175
      bool operator!=(const Edge i) const {return n!=i.n;}
alpar@164
   176
      bool operator<(const Edge i) const {return n<i.n;}
klao@946
   177
    };
alpar@905
   178
klao@946
   179
    void first(Node& node) const {
klao@946
   180
      node.n = nodes.size() - 1;
klao@946
   181
    }
klao@946
   182
klao@946
   183
    static void next(Node& node) {
klao@946
   184
      --node.n;
klao@946
   185
    }
klao@946
   186
klao@946
   187
    void first(Edge& edge) const {
klao@946
   188
      edge.n = edges.size() - 1;
klao@946
   189
    }
klao@946
   190
klao@946
   191
    static void next(Edge& edge) {
klao@946
   192
      --edge.n;
klao@946
   193
    }
klao@946
   194
klao@946
   195
    void firstOut(Edge& edge, const Node& node) const {
klao@946
   196
      edge.n = nodes[node.n].first_out;
klao@946
   197
    }
klao@946
   198
klao@946
   199
    void nextOut(Edge& edge) const {
klao@946
   200
      edge.n = edges[edge.n].next_out;
klao@946
   201
    }
klao@946
   202
klao@946
   203
    void firstIn(Edge& edge, const Node& node) const {
klao@946
   204
      edge.n = nodes[node.n].first_in;
klao@946
   205
    }
alpar@104
   206
    
klao@946
   207
    void nextIn(Edge& edge) const {
klao@946
   208
      edge.n = edges[edge.n].next_in;
klao@946
   209
    }
alpar@105
   210
alpar@1284
   211
    Node _split(Node n, bool connect = true)
alpar@1284
   212
    {
alpar@1284
   213
      Node b = addNode();
alpar@1284
   214
      nodes[b.n].first_out=nodes[n.n].first_out;
alpar@1284
   215
      nodes[n.n].first_out=-1;
alpar@1284
   216
      for(int i=nodes[b.n].first_out;i!=-1;i++) edges[i].source=b.n;
alpar@1284
   217
      if(connect) addEdge(n,b);
alpar@1284
   218
      return b;
alpar@1284
   219
    }
alpar@1284
   220
alpar@104
   221
  };
alpar@185
   222
deba@1979
   223
  typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
deba@937
   224
deba@1791
   225
  /// \ingroup graphs
alpar@1161
   226
alpar@950
   227
  ///A smart graph class.
deba@937
   228
alpar@950
   229
  ///This is a simple and fast graph implementation.
alpar@950
   230
  ///It is also quite memory efficient, but at the price
alpar@974
   231
  ///that <b> it does support only limited (only stack-like)
alpar@974
   232
  ///node and edge deletions</b>.
alpar@950
   233
  ///It conforms to 
klao@959
   234
  ///the \ref concept::ExtendableGraph "ExtendableGraph" concept.
klao@959
   235
  ///\sa concept::ExtendableGraph.
alpar@950
   236
  ///
alpar@950
   237
  ///\author Alpar Juttner
deba@1669
   238
  class SmartGraph : public ExtendedSmartGraphBase {
alpar@969
   239
  public:
deba@1979
   240
deba@1979
   241
    typedef ExtendedSmartGraphBase Parent;
deba@1979
   242
alpar@1770
   243
    class Snapshot;
alpar@1770
   244
    friend class Snapshot;
alpar@973
   245
alpar@1011
   246
  protected:
alpar@1770
   247
    void restoreSnapshot(const Snapshot &s)
alpar@973
   248
    {
alpar@1457
   249
      while(s.edge_num<edges.size()) {
deba@1040
   250
	Parent::getNotifier(Edge()).erase(Edge(edges.size()-1));
alpar@986
   251
	nodes[edges.back().target].first_in=edges.back().next_in;
alpar@986
   252
	nodes[edges.back().source].first_out=edges.back().next_out;
alpar@973
   253
	edges.pop_back();
alpar@973
   254
      }
alpar@973
   255
      //nodes.resize(s.nodes_num);
alpar@1457
   256
      while(s.node_num<nodes.size()) {
deba@1040
   257
	Parent::getNotifier(Node()).erase(Node(nodes.size()-1));
alpar@973
   258
	nodes.pop_back();
alpar@973
   259
      }
alpar@1011
   260
    }    
alpar@1011
   261
alpar@1011
   262
  public:
alpar@1284
   263
alpar@1284
   264
    ///Split a node.
alpar@1284
   265
    
alpar@1284
   266
    ///This function splits a node. First a new node is added to the graph,
alpar@1284
   267
    ///then the source of each outgoing edge of \c n is moved to this new node.
alpar@1284
   268
    ///If \c connect is \c true (this is the default value), then a new edge
alpar@1284
   269
    ///from \c n to the newly created node is also added.
alpar@1284
   270
    ///\return The newly created node.
alpar@1284
   271
    ///
alpar@1284
   272
    ///\note The <tt>Edge</tt>s
alpar@1284
   273
    ///referencing a moved edge remain
alpar@1284
   274
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1284
   275
    ///may be invalidated.
alpar@1770
   276
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1284
   277
    ///feature.
alpar@1284
   278
    ///\todo It could be implemented in a bit faster way.
alpar@1284
   279
    Node split(Node n, bool connect = true) 
alpar@1284
   280
    {
deba@1718
   281
      Node b = _split(n,connect);
deba@1718
   282
      return b;
alpar@1284
   283
    }
alpar@1284
   284
  
alpar@1284
   285
alpar@1011
   286
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   287
alpar@1011
   288
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   289
    ///
alpar@1011
   290
    ///The newly added nodes and edges can be removed using the
alpar@1011
   291
    ///restore() function.
alpar@1011
   292
    ///\note After you restore a state, you cannot restore
alpar@1011
   293
    ///a later state, in other word you cannot add again the edges deleted
alpar@1770
   294
    ///by restore() using another Snapshot instance.
alpar@1011
   295
    ///
alpar@1770
   296
    class Snapshot 
alpar@1011
   297
    {
alpar@1011
   298
      SmartGraph *g;
alpar@1011
   299
    protected:
alpar@1011
   300
      friend class SmartGraph;
alpar@1011
   301
      unsigned int node_num;
alpar@1011
   302
      unsigned int edge_num;
alpar@1011
   303
    public:
zsuzska@1274
   304
      ///Default constructor.
alpar@1011
   305
      
zsuzska@1274
   306
      ///Default constructor.
alpar@1011
   307
      ///To actually make a snapshot you must call save().
alpar@1011
   308
      ///
alpar@1770
   309
      Snapshot() : g(0) {}
alpar@1011
   310
      ///Constructor that immediately makes a snapshot
alpar@1011
   311
      
alpar@1011
   312
      ///This constructor immediately makes a snapshot of the graph.
alpar@1011
   313
      ///\param _g The graph we make a snapshot of.
alpar@1770
   314
      Snapshot(SmartGraph &_g) :g(&_g) {
alpar@1011
   315
	node_num=g->nodes.size();
alpar@1011
   316
	edge_num=g->edges.size();
alpar@1011
   317
      }
alpar@1011
   318
alpar@1011
   319
      ///Make a snapshot.
alpar@1011
   320
alpar@1011
   321
      ///Make a snapshot of the graph.
alpar@1011
   322
      ///
alpar@1011
   323
      ///This function can be called more than once. In case of a repeated
alpar@1011
   324
      ///call, the previous snapshot gets lost.
alpar@1011
   325
      ///\param _g The graph we make the snapshot of.
alpar@1011
   326
      void save(SmartGraph &_g) 
alpar@1011
   327
      {
alpar@1011
   328
	g=&_g;
alpar@1011
   329
	node_num=g->nodes.size();
alpar@1011
   330
	edge_num=g->edges.size();
alpar@1011
   331
      }
alpar@1011
   332
alpar@1011
   333
      ///Undo the changes until a snapshot.
alpar@1011
   334
      
alpar@1011
   335
      ///Undo the changes until a snapshot created by save().
alpar@1011
   336
      ///
alpar@1011
   337
      ///\note After you restored a state, you cannot restore
alpar@1011
   338
      ///a later state, in other word you cannot add again the edges deleted
alpar@1011
   339
      ///by restore().
alpar@1011
   340
      ///
alpar@1011
   341
      ///\todo This function might be called undo().
alpar@1011
   342
      
alpar@1011
   343
      void restore()
alpar@1011
   344
      {
alpar@1770
   345
	g->restoreSnapshot(*this);
alpar@1011
   346
      }
alpar@1011
   347
    };
alpar@973
   348
  };
klao@1034
   349
klao@1034
   350
klao@1034
   351
  /**************** Undirected List Graph ****************/
klao@1034
   352
deba@1979
   353
  typedef UGraphExtender<UGraphBaseExtender<SmartGraphBase> >
deba@1979
   354
  ExtendedSmartUGraphBase;
klao@1034
   355
klao@1909
   356
  /// \ingroup graphs
alpar@1035
   357
  ///
klao@1909
   358
  /// \brief A smart undirected graph class.
alpar@1035
   359
  ///
klao@1909
   360
  /// This is a simple and fast undirected graph implementation.
klao@1909
   361
  /// It is also quite memory efficient, but at the price
klao@1909
   362
  /// that <b> it does support only limited (only stack-like)
klao@1909
   363
  /// node and edge deletions</b>.
klao@1909
   364
  /// Except from this it conforms to 
klao@1909
   365
  /// the \ref concept::UGraph "UGraph" concept.
klao@1909
   366
  /// \sa concept::UGraph.
klao@1909
   367
  ///
klao@1909
   368
  /// \todo Snapshot hasn't been implemented yet.
klao@1909
   369
  ///
klao@1909
   370
  class SmartUGraph : public ExtendedSmartUGraphBase {
klao@1034
   371
  };
klao@1034
   372
deba@1820
   373
deba@1910
   374
  class SmartBpUGraphBase {
deba@1820
   375
  public:
deba@1820
   376
deba@1820
   377
    class NodeSetError : public LogicError {
deba@1820
   378
      virtual const char* exceptionName() const { 
deba@1910
   379
	return "lemon::SmartBpUGraph::NodeSetError";
deba@1820
   380
      }
deba@1820
   381
    };
deba@1820
   382
deba@1820
   383
  protected:
deba@1820
   384
deba@1820
   385
    struct NodeT {
deba@1820
   386
      int first;
deba@1820
   387
      NodeT() {}
deba@1820
   388
      NodeT(int _first) : first(_first) {}
deba@1820
   389
    };
deba@1820
   390
deba@1820
   391
    struct EdgeT {
deba@1910
   392
      int aNode, next_out;
deba@1910
   393
      int bNode, next_in;
deba@1820
   394
    };
deba@1820
   395
deba@1910
   396
    std::vector<NodeT> aNodes;
deba@1910
   397
    std::vector<NodeT> bNodes;
deba@1820
   398
deba@1820
   399
    std::vector<EdgeT> edges;
deba@1820
   400
deba@1820
   401
  public:
deba@1820
   402
  
deba@1820
   403
    class Node {
deba@1910
   404
      friend class SmartBpUGraphBase;
deba@1820
   405
    protected:
deba@1820
   406
      int id;
deba@1820
   407
deba@1820
   408
      Node(int _id) : id(_id) {}
deba@1820
   409
    public:
deba@1820
   410
      Node() {}
deba@1820
   411
      Node(Invalid) { id = -1; }
deba@1820
   412
      bool operator==(const Node i) const {return id==i.id;}
deba@1820
   413
      bool operator!=(const Node i) const {return id!=i.id;}
deba@1820
   414
      bool operator<(const Node i) const {return id<i.id;}
deba@1820
   415
    };
deba@1820
   416
deba@1820
   417
    class Edge {
deba@1910
   418
      friend class SmartBpUGraphBase;
deba@1820
   419
    protected:
deba@1820
   420
      int id;
deba@1820
   421
deba@1820
   422
      Edge(int _id) { id = _id;}
deba@1820
   423
    public:
deba@1820
   424
      Edge() {}
deba@1820
   425
      Edge (Invalid) { id = -1; }
deba@1820
   426
      bool operator==(const Edge i) const {return id==i.id;}
deba@1820
   427
      bool operator!=(const Edge i) const {return id!=i.id;}
deba@1820
   428
      bool operator<(const Edge i) const {return id<i.id;}
deba@1820
   429
    };
deba@1820
   430
deba@1910
   431
    void firstANode(Node& node) const {
deba@1910
   432
      node.id = 2 * aNodes.size() - 2;
deba@1820
   433
      if (node.id < 0) node.id = -1; 
deba@1820
   434
    }
deba@1910
   435
    void nextANode(Node& node) const {
deba@1820
   436
      node.id -= 2;
deba@1820
   437
      if (node.id < 0) node.id = -1; 
deba@1820
   438
    }
deba@1820
   439
deba@1910
   440
    void firstBNode(Node& node) const {
deba@1910
   441
      node.id = 2 * bNodes.size() - 1;
deba@1820
   442
    }
deba@1910
   443
    void nextBNode(Node& node) const {
deba@1820
   444
      node.id -= 2;
deba@1820
   445
    }
deba@1820
   446
deba@1820
   447
    void first(Node& node) const {
deba@1910
   448
      if (aNodes.size() > 0) {
deba@1910
   449
	node.id = 2 * aNodes.size() - 2;
deba@1820
   450
      } else {
deba@1910
   451
	node.id = 2 * bNodes.size() - 1;
deba@1820
   452
      }
deba@1820
   453
    }
deba@1820
   454
    void next(Node& node) const {
deba@1820
   455
      node.id -= 2;
deba@1820
   456
      if (node.id == -2) {
deba@1910
   457
	node.id = 2 * bNodes.size() - 1;
deba@1820
   458
      }
deba@1820
   459
    }
deba@1820
   460
  
deba@1820
   461
    void first(Edge& edge) const {
deba@1820
   462
      edge.id = edges.size() - 1;
deba@1820
   463
    }
deba@1820
   464
    void next(Edge& edge) const {
deba@1820
   465
      --edge.id;
deba@1820
   466
    }
deba@1820
   467
deba@1910
   468
    void firstOut(Edge& edge, const Node& node) const {
deba@1820
   469
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@1910
   470
      edge.id = aNodes[node.id >> 1].first;
deba@1820
   471
    }
deba@1910
   472
    void nextOut(Edge& edge) const {
deba@1910
   473
      edge.id = edges[edge.id].next_out;
deba@1820
   474
    }
deba@1820
   475
deba@1910
   476
    void firstIn(Edge& edge, const Node& node) const {
deba@1820
   477
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@1910
   478
      edge.id = bNodes[node.id >> 1].first;
deba@1820
   479
    }
deba@1910
   480
    void nextIn(Edge& edge) const {
deba@1910
   481
      edge.id = edges[edge.id].next_in;
deba@1820
   482
    }
deba@1820
   483
deba@1820
   484
    static int id(const Node& node) {
deba@1820
   485
      return node.id;
deba@1820
   486
    }
deba@1820
   487
    static Node nodeFromId(int id) {
deba@1820
   488
      return Node(id);
deba@1820
   489
    }
deba@1820
   490
    int maxNodeId() const {
deba@1910
   491
      return aNodes.size() > bNodes.size() ?
deba@1910
   492
	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
deba@1820
   493
    }
deba@1820
   494
  
deba@1820
   495
    static int id(const Edge& edge) {
deba@1820
   496
      return edge.id;
deba@1820
   497
    }
deba@1820
   498
    static Edge edgeFromId(int id) {
deba@1820
   499
      return Edge(id);
deba@1820
   500
    }
deba@1820
   501
    int maxEdgeId() const {
deba@1820
   502
      return edges.size();
deba@1820
   503
    }
deba@1820
   504
  
deba@1910
   505
    static int aNodeId(const Node& node) {
deba@1820
   506
      return node.id >> 1;
deba@1820
   507
    }
deba@1995
   508
    static Node fromANodeId(int id) {
deba@1820
   509
      return Node(id << 1);
deba@1820
   510
    }
deba@1910
   511
    int maxANodeId() const {
deba@1910
   512
      return aNodes.size();
deba@1820
   513
    }
deba@1820
   514
deba@1910
   515
    static int bNodeId(const Node& node) {
deba@1820
   516
      return node.id >> 1;
deba@1820
   517
    }
deba@1910
   518
    static Node fromBNodeId(int id) {
deba@1820
   519
      return Node((id << 1) + 1);
deba@1820
   520
    }
deba@1910
   521
    int maxBNodeId() const {
deba@1910
   522
      return bNodes.size();
deba@1820
   523
    }
deba@1820
   524
deba@1910
   525
    Node aNode(const Edge& edge) const {
deba@1910
   526
      return Node(edges[edge.id].aNode);
deba@1820
   527
    }
deba@1910
   528
    Node bNode(const Edge& edge) const {
deba@1910
   529
      return Node(edges[edge.id].bNode);
deba@1820
   530
    }
deba@1820
   531
deba@1910
   532
    static bool aNode(const Node& node) {
deba@1820
   533
      return (node.id & 1) == 0;
deba@1820
   534
    }
deba@1820
   535
deba@1910
   536
    static bool bNode(const Node& node) {
deba@1820
   537
      return (node.id & 1) == 1;
deba@1820
   538
    }
deba@1820
   539
deba@1910
   540
    Node addANode() {
deba@1820
   541
      NodeT nodeT;
deba@1820
   542
      nodeT.first = -1;
deba@1910
   543
      aNodes.push_back(nodeT);
deba@1910
   544
      return Node(aNodes.size() * 2 - 2);
deba@1820
   545
    }
deba@1820
   546
deba@1910
   547
    Node addBNode() {
deba@1820
   548
      NodeT nodeT;
deba@1820
   549
      nodeT.first = -1;
deba@1910
   550
      bNodes.push_back(nodeT);
deba@1910
   551
      return Node(bNodes.size() * 2 - 1);
deba@1820
   552
    }
deba@1820
   553
deba@1820
   554
    Edge addEdge(const Node& source, const Node& target) {
deba@1820
   555
      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
deba@1820
   556
      EdgeT edgeT;
deba@1820
   557
      if ((source.id & 1) == 0) {
deba@1910
   558
	edgeT.aNode = source.id;
deba@1910
   559
	edgeT.bNode = target.id;
deba@1820
   560
      } else {
deba@1910
   561
	edgeT.aNode = target.id;
deba@1910
   562
	edgeT.bNode = source.id;
deba@1820
   563
      }
deba@1910
   564
      edgeT.next_out = aNodes[edgeT.aNode >> 1].first;
deba@1910
   565
      aNodes[edgeT.aNode >> 1].first = edges.size();
deba@1910
   566
      edgeT.next_in = bNodes[edgeT.bNode >> 1].first;
deba@1910
   567
      bNodes[edgeT.bNode >> 1].first = edges.size();
deba@1820
   568
      edges.push_back(edgeT);
deba@1820
   569
      return Edge(edges.size() - 1);
deba@1820
   570
    }
deba@1820
   571
deba@1820
   572
    void clear() {
deba@1910
   573
      aNodes.clear();
deba@1910
   574
      bNodes.clear();
deba@1820
   575
      edges.clear();
deba@1820
   576
    }
deba@1820
   577
deba@2031
   578
    typedef True NodeNumTag;
deba@2031
   579
    int nodeNum() const { return aNodes.size() + bNodes.size(); }
deba@2031
   580
    int aNodeNum() const { return aNodes.size(); }
deba@2031
   581
    int bNodeNum() const { return bNodes.size(); }
deba@2031
   582
deba@2031
   583
    typedef True EdgeNumTag;
deba@2031
   584
    int edgeNum() const { return edges.size(); }
deba@2031
   585
deba@1820
   586
  };
deba@1820
   587
deba@1820
   588
deba@1979
   589
  typedef BpUGraphExtender< BpUGraphBaseExtender<
deba@1979
   590
    SmartBpUGraphBase> > ExtendedSmartBpUGraphBase;
deba@1820
   591
deba@1910
   592
  /// \ingroup graphs
deba@1910
   593
  ///
deba@1910
   594
  /// \brief A smart bipartite undirected graph class.
deba@1910
   595
  ///
deba@1910
   596
  /// This is a simple and fast bipartite undirected graph implementation.
deba@1910
   597
  /// It is also quite memory efficient, but at the price
deba@1910
   598
  /// that <b> it does not support node and edge deletions</b>.
deba@1910
   599
  /// Except from this it conforms to 
deba@1910
   600
  /// the \ref concept::BpUGraph "BpUGraph" concept.
deba@1910
   601
  /// \sa concept::BpUGraph.
deba@1910
   602
  ///
deba@1910
   603
  class SmartBpUGraph : public ExtendedSmartBpUGraphBase {};
deba@1820
   604
alpar@950
   605
  
alpar@407
   606
  /// @}  
alpar@921
   607
} //namespace lemon
alpar@104
   608
alpar@157
   609
alpar@921
   610
#endif //LEMON_SMART_GRAPH_H