lemon/full_graph.h
author deba
Mon, 03 Apr 2006 09:45:23 +0000
changeset 2031 080d51024ac5
parent 1999 2ff283124dfc
child 2061 7ab148f53d66
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@591
    18
alpar@921
    19
#ifndef LEMON_FULL_GRAPH_H
alpar@921
    20
#define LEMON_FULL_GRAPH_H
alpar@591
    21
deba@983
    22
#include <cmath>
deba@983
    23
deba@1999
    24
#include <lemon/bits/base_extender.h>
deba@1791
    25
#include <lemon/bits/graph_extender.h>
deba@1566
    26
deba@1993
    27
#include <lemon/bits/invalid.h>
deba@1993
    28
#include <lemon/bits/utility.h>
klao@977
    29
klao@977
    30
alpar@591
    31
///\ingroup graphs
alpar@591
    32
///\file
klao@1909
    33
///\brief FullGraph and FullUGraph classes.
alpar@591
    34
alpar@591
    35
alpar@921
    36
namespace lemon {
alpar@591
    37
deba@1986
    38
  /// \brief Base of the FullGrpah.
deba@1986
    39
  ///
deba@1986
    40
  /// Base of the FullGrpah.
klao@946
    41
  class FullGraphBase {
deba@1566
    42
    int _nodeNum;
deba@1566
    43
    int _edgeNum;
alpar@591
    44
  public:
deba@782
    45
klao@946
    46
    typedef FullGraphBase Graph;
alpar@591
    47
alpar@591
    48
    class Node;
alpar@591
    49
    class Edge;
deba@782
    50
alpar@591
    51
  public:
alpar@591
    52
klao@946
    53
    FullGraphBase() {}
klao@946
    54
klao@946
    55
alpar@591
    56
    ///Creates a full graph with \c n nodes.
deba@1566
    57
    void construct(int n) { _nodeNum = n; _edgeNum = n * n; }
alpar@591
    58
    
klao@977
    59
    typedef True NodeNumTag;
klao@977
    60
    typedef True EdgeNumTag;
klao@977
    61
deba@1986
    62
    /// \brief Returns the node with the given index.
deba@1986
    63
    ///
deba@1986
    64
    /// Returns the node with the given index. Because it is a
deba@1986
    65
    /// static size graph the node's of the graph can be indiced
deba@1986
    66
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@1986
    67
    /// the node can accessed by the \e index() member.
deba@1986
    68
    Node operator()(int index) const { return Node(index); }
deba@1986
    69
deba@1986
    70
    /// \brief Returns the index of the node.
deba@1986
    71
    ///
deba@1986
    72
    /// Returns the index of the node. Because it is a
deba@1986
    73
    /// static size graph the node's of the graph can be indiced
deba@1986
    74
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@1986
    75
    /// the node can accessed by the \e index() member.
deba@1986
    76
    int index(const Node& node) const { return node.id; }
deba@1986
    77
alpar@813
    78
    ///Number of nodes.
deba@1566
    79
    int nodeNum() const { return _nodeNum; }
alpar@813
    80
    ///Number of edges.
deba@1566
    81
    int edgeNum() const { return _edgeNum; }
alpar@591
    82
alpar@813
    83
    /// Maximum node ID.
alpar@813
    84
    
alpar@813
    85
    /// Maximum node ID.
alpar@813
    86
    ///\sa id(Node)
deba@1791
    87
    int maxNodeId() const { return _nodeNum-1; }
alpar@813
    88
    /// Maximum edge ID.
alpar@813
    89
    
alpar@813
    90
    /// Maximum edge ID.
alpar@813
    91
    ///\sa id(Edge)
deba@1791
    92
    int maxEdgeId() const { return _edgeNum-1; }
alpar@591
    93
deba@1566
    94
    Node source(Edge e) const { return e.id % _nodeNum; }
deba@1566
    95
    Node target(Edge e) const { return e.id / _nodeNum; }
alpar@591
    96
alpar@591
    97
alpar@813
    98
    /// Node ID.
alpar@813
    99
    
alpar@813
   100
    /// The ID of a valid Node is a nonnegative integer not greater than
alpar@813
   101
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
alpar@813
   102
    /// and the greatest node ID can be actually less then \ref maxNodeId().
alpar@813
   103
    ///
alpar@813
   104
    /// The ID of the \ref INVALID node is -1.
alpar@813
   105
    ///\return The ID of the node \c v. 
klao@946
   106
klao@946
   107
    static int id(Node v) { return v.id; }
alpar@813
   108
    /// Edge ID.
alpar@813
   109
    
alpar@813
   110
    /// The ID of a valid Edge is a nonnegative integer not greater than
alpar@813
   111
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
alpar@813
   112
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
alpar@813
   113
    ///
alpar@813
   114
    /// The ID of the \ref INVALID edge is -1.
alpar@813
   115
    ///\return The ID of the edge \c e. 
klao@946
   116
    static int id(Edge e) { return e.id; }
alpar@591
   117
deba@1791
   118
    static Node nodeFromId(int id) { return Node(id);}
deba@1106
   119
    
deba@1791
   120
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   121
deba@1566
   122
    typedef True FindEdgeTag;
deba@1566
   123
alpar@774
   124
    /// Finds an edge between two nodes.
alpar@774
   125
    
alpar@774
   126
    /// Finds an edge from node \c u to node \c v.
alpar@774
   127
    ///
alpar@774
   128
    /// If \c prev is \ref INVALID (this is the default value), then
alpar@774
   129
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
alpar@774
   130
    /// the next edge from \c u to \c v after \c prev.
alpar@774
   131
    /// \return The found edge or INVALID if there is no such an edge.
deba@1566
   132
    Edge findEdge(Node u,Node v, Edge prev = INVALID) const {
klao@946
   133
      return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
alpar@774
   134
    }
alpar@774
   135
    
alpar@774
   136
      
alpar@591
   137
    class Node {
klao@946
   138
      friend class FullGraphBase;
alpar@591
   139
alpar@591
   140
    protected:
klao@946
   141
      int id;
alpar@1643
   142
      Node(int _id) : id(_id) {}
alpar@591
   143
    public:
alpar@591
   144
      Node() {}
alpar@1643
   145
      Node (Invalid) : id(-1) {}
klao@946
   146
      bool operator==(const Node node) const {return id == node.id;}
klao@946
   147
      bool operator!=(const Node node) const {return id != node.id;}
klao@946
   148
      bool operator<(const Node node) const {return id < node.id;}
alpar@591
   149
    };
alpar@591
   150
    
klao@946
   151
klao@946
   152
klao@946
   153
    class Edge {
klao@946
   154
      friend class FullGraphBase;
klao@946
   155
      
klao@946
   156
    protected:
deba@1566
   157
      int id;  // _nodeNum * target + source;
klao@946
   158
klao@946
   159
      Edge(int _id) : id(_id) {}
klao@946
   160
alpar@986
   161
      Edge(const FullGraphBase& _graph, int source, int target) 
deba@1566
   162
	: id(_graph._nodeNum * target+source) {}
alpar@591
   163
    public:
klao@946
   164
      Edge() { }
klao@946
   165
      Edge (Invalid) { id = -1; }
klao@946
   166
      bool operator==(const Edge edge) const {return id == edge.id;}
klao@946
   167
      bool operator!=(const Edge edge) const {return id != edge.id;}
klao@946
   168
      bool operator<(const Edge edge) const {return id < edge.id;}
alpar@591
   169
    };
alpar@591
   170
klao@946
   171
    void first(Node& node) const {
deba@1566
   172
      node.id = _nodeNum-1;
klao@946
   173
    }
alpar@591
   174
klao@946
   175
    static void next(Node& node) {
klao@946
   176
      --node.id;
klao@946
   177
    }
klao@946
   178
klao@946
   179
    void first(Edge& edge) const {
deba@1566
   180
      edge.id = _edgeNum-1;
klao@946
   181
    }
klao@946
   182
klao@946
   183
    static void next(Edge& edge) {
klao@946
   184
      --edge.id;
klao@946
   185
    }
klao@946
   186
klao@946
   187
    void firstOut(Edge& edge, const Node& node) const {
deba@1566
   188
      edge.id = _edgeNum + node.id - _nodeNum;
klao@946
   189
    }
klao@946
   190
klao@946
   191
    void nextOut(Edge& edge) const {
deba@1566
   192
      edge.id -= _nodeNum;
klao@946
   193
      if (edge.id < 0) edge.id = -1;
klao@946
   194
    }
klao@946
   195
klao@946
   196
    void firstIn(Edge& edge, const Node& node) const {
deba@1566
   197
      edge.id = node.id * _nodeNum;
klao@946
   198
    }
alpar@591
   199
    
klao@946
   200
    void nextIn(Edge& edge) const {
klao@946
   201
      ++edge.id;
deba@1566
   202
      if (edge.id % _nodeNum == 0) edge.id = -1;
klao@946
   203
    }
alpar@591
   204
alpar@591
   205
  };
alpar@591
   206
deba@1979
   207
  typedef GraphExtender<FullGraphBase> ExtendedFullGraphBase;
klao@946
   208
deba@1566
   209
  /// \ingroup graphs
alpar@951
   210
  ///
deba@1566
   211
  /// \brief A full graph class.
deba@1566
   212
  ///
deba@1566
   213
  /// This is a simple and fast directed full graph implementation.
deba@1566
   214
  /// It is completely static, so you can neither add nor delete either
deba@1566
   215
  /// edges or nodes.
deba@1566
   216
  /// Thus it conforms to
deba@1566
   217
  /// the \ref concept::StaticGraph "StaticGraph" concept
deba@1566
   218
  /// \sa concept::StaticGraph.
deba@1566
   219
  ///
deba@1986
   220
  /// \sa FullGraphBase
deba@1986
   221
  /// \sa FullUGraph
deba@1986
   222
  ///
deba@1566
   223
  /// \author Alpar Juttner
deba@1669
   224
  class FullGraph : public ExtendedFullGraphBase {
klao@946
   225
  public:
klao@946
   226
deba@1979
   227
    typedef ExtendedFullGraphBase Parent;
deba@1979
   228
deba@1979
   229
    /// \brief Constructor
deba@1987
   230
    FullGraph() { construct(0); }
deba@1987
   231
deba@1987
   232
    /// \brief Constructor
deba@1979
   233
    ///
klao@946
   234
    FullGraph(int n) { construct(n); }
deba@1979
   235
deba@1979
   236
    /// \brief Resize the graph
deba@1979
   237
    ///
deba@1986
   238
    /// Resize the graph. The function will fully destroy and build the graph.
deba@1986
   239
    /// This cause that the maps of the graph will reallocated
deba@1986
   240
    /// automatically and the previous values will be lost.
deba@1979
   241
    void resize(int n) {
deba@1979
   242
      Parent::getNotifier(Edge()).clear();
deba@1979
   243
      Parent::getNotifier(Node()).clear();
deba@1979
   244
      construct(n);
deba@1979
   245
      Parent::getNotifier(Node()).build();
deba@1979
   246
      Parent::getNotifier(Edge()).build();
deba@1979
   247
    }
klao@946
   248
  };
klao@946
   249
deba@983
   250
deba@1986
   251
  /// \brief Base of the FullUGrpah.
deba@1986
   252
  ///
deba@1986
   253
  /// Base of the FullUGrpah.
klao@1909
   254
  class FullUGraphBase {
deba@1566
   255
    int _nodeNum;
deba@1566
   256
    int _edgeNum;
deba@983
   257
  public:
deba@983
   258
klao@1909
   259
    typedef FullUGraphBase Graph;
deba@983
   260
deba@983
   261
    class Node;
deba@983
   262
    class Edge;
deba@983
   263
deba@983
   264
  public:
deba@983
   265
klao@1909
   266
    FullUGraphBase() {}
deba@983
   267
deba@983
   268
deba@983
   269
    ///Creates a full graph with \c n nodes.
deba@1566
   270
    void construct(int n) { _nodeNum = n; _edgeNum = n * (n - 1) / 2; }
deba@1986
   271
deba@1986
   272
    /// \brief Returns the node with the given index.
deba@983
   273
    ///
deba@1986
   274
    /// Returns the node with the given index. Because it is a
deba@1986
   275
    /// static size graph the node's of the graph can be indiced
deba@1986
   276
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@1986
   277
    /// the node can accessed by the \e index() member.
deba@1986
   278
    Node operator()(int index) const { return Node(index); }
deba@1986
   279
deba@1986
   280
    /// \brief Returns the index of the node.
deba@1986
   281
    ///
deba@1986
   282
    /// Returns the index of the node. Because it is a
deba@1986
   283
    /// static size graph the node's of the graph can be indiced
deba@1986
   284
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@1986
   285
    /// the node can accessed by the \e index() member.
deba@1986
   286
    int index(const Node& node) const { return node.id; }
deba@1986
   287
deba@983
   288
    typedef True NodeNumTag;
deba@983
   289
    typedef True EdgeNumTag;
deba@983
   290
deba@983
   291
    ///Number of nodes.
deba@1566
   292
    int nodeNum() const { return _nodeNum; }
deba@983
   293
    ///Number of edges.
deba@1566
   294
    int edgeNum() const { return _edgeNum; }
deba@983
   295
deba@983
   296
    /// Maximum node ID.
deba@983
   297
    
deba@983
   298
    /// Maximum node ID.
deba@983
   299
    ///\sa id(Node)
deba@1791
   300
    int maxNodeId() const { return _nodeNum-1; }
deba@983
   301
    /// Maximum edge ID.
deba@983
   302
    
deba@983
   303
    /// Maximum edge ID.
deba@983
   304
    ///\sa id(Edge)
deba@1791
   305
    int maxEdgeId() const { return _edgeNum-1; }
deba@983
   306
alpar@986
   307
    Node source(Edge e) const { 
deba@983
   308
      /// \todo we may do it faster
alpar@1643
   309
      return Node(((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2);
deba@983
   310
    }
deba@983
   311
alpar@986
   312
    Node target(Edge e) const { 
alpar@986
   313
      int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
alpar@1643
   314
      return Node(e.id - (source) * (source - 1) / 2);
deba@983
   315
    }
deba@983
   316
deba@983
   317
deba@1986
   318
    /// \brief Node ID.
deba@1986
   319
    ///
deba@983
   320
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@983
   321
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@983
   322
    /// and the greatest node ID can be actually less then \ref maxNodeId().
deba@983
   323
    ///
deba@983
   324
    /// The ID of the \ref INVALID node is -1.
deba@1986
   325
    /// \return The ID of the node \c v. 
deba@983
   326
deba@983
   327
    static int id(Node v) { return v.id; }
deba@1986
   328
deba@1986
   329
    /// \brief Edge ID.
deba@1986
   330
    ///
deba@983
   331
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@983
   332
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@983
   333
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
deba@983
   334
    ///
deba@983
   335
    /// The ID of the \ref INVALID edge is -1.
deba@983
   336
    ///\return The ID of the edge \c e. 
deba@983
   337
    static int id(Edge e) { return e.id; }
deba@983
   338
deba@1986
   339
    /// \brief Finds an edge between two nodes.
deba@1986
   340
    ///
deba@983
   341
    /// Finds an edge from node \c u to node \c v.
deba@983
   342
    ///
deba@983
   343
    /// If \c prev is \ref INVALID (this is the default value), then
deba@983
   344
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
deba@983
   345
    /// the next edge from \c u to \c v after \c prev.
deba@983
   346
    /// \return The found edge or INVALID if there is no such an edge.
deba@1703
   347
    Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
deba@1986
   348
      if (prev.id != -1 || u.id <= v.id) return Edge(-1);
deba@1703
   349
      return Edge(u.id * (u.id - 1) / 2 + v.id);
deba@983
   350
    }
deba@1703
   351
deba@1703
   352
    typedef True FindEdgeTag;
deba@983
   353
    
deba@983
   354
      
deba@983
   355
    class Node {
klao@1909
   356
      friend class FullUGraphBase;
deba@983
   357
deba@983
   358
    protected:
deba@983
   359
      int id;
deba@983
   360
      Node(int _id) { id = _id;}
deba@983
   361
    public:
deba@983
   362
      Node() {}
deba@983
   363
      Node (Invalid) { id = -1; }
deba@983
   364
      bool operator==(const Node node) const {return id == node.id;}
deba@983
   365
      bool operator!=(const Node node) const {return id != node.id;}
deba@983
   366
      bool operator<(const Node node) const {return id < node.id;}
deba@983
   367
    };
deba@983
   368
    
deba@983
   369
deba@983
   370
deba@983
   371
    class Edge {
klao@1909
   372
      friend class FullUGraphBase;
deba@983
   373
      
deba@983
   374
    protected:
deba@1566
   375
      int id;  // _nodeNum * target + source;
deba@983
   376
deba@983
   377
      Edge(int _id) : id(_id) {}
deba@983
   378
deba@983
   379
    public:
deba@983
   380
      Edge() { }
deba@983
   381
      Edge (Invalid) { id = -1; }
deba@983
   382
      bool operator==(const Edge edge) const {return id == edge.id;}
deba@983
   383
      bool operator!=(const Edge edge) const {return id != edge.id;}
deba@983
   384
      bool operator<(const Edge edge) const {return id < edge.id;}
deba@983
   385
    };
deba@983
   386
deba@983
   387
    void first(Node& node) const {
deba@1703
   388
      node.id = _nodeNum - 1;
deba@983
   389
    }
deba@983
   390
deba@983
   391
    static void next(Node& node) {
deba@983
   392
      --node.id;
deba@983
   393
    }
deba@983
   394
deba@983
   395
    void first(Edge& edge) const {
deba@1703
   396
      edge.id = _edgeNum - 1;
deba@983
   397
    }
deba@983
   398
deba@983
   399
    static void next(Edge& edge) {
deba@983
   400
      --edge.id;
deba@983
   401
    }
deba@983
   402
deba@983
   403
    void firstOut(Edge& edge, const Node& node) const {      
deba@1703
   404
      int src = node.id;
deba@1703
   405
      int trg = 0;
deba@1703
   406
      edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
deba@983
   407
    }
deba@983
   408
deba@983
   409
    /// \todo with specialized iterators we can make faster iterating
deba@1703
   410
    void nextOut(Edge& edge) const {
deba@1703
   411
      int src = source(edge).id;
deba@1703
   412
      int trg = target(edge).id;
deba@1703
   413
      ++trg;
deba@1703
   414
      edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
deba@983
   415
    }
deba@983
   416
deba@983
   417
    void firstIn(Edge& edge, const Node& node) const {
deba@1703
   418
      int src = node.id + 1;
deba@1703
   419
      int trg = node.id;
deba@1703
   420
      edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
deba@983
   421
    }
deba@983
   422
    
deba@1703
   423
    void nextIn(Edge& edge) const {
deba@1703
   424
      int src = source(edge).id;
deba@1703
   425
      int trg = target(edge).id;
deba@1703
   426
      ++src;
deba@1703
   427
      edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
deba@983
   428
    }
deba@983
   429
deba@983
   430
  };
deba@983
   431
deba@1979
   432
  typedef UGraphExtender<UGraphBaseExtender<FullUGraphBase> > 
deba@1979
   433
  ExtendedFullUGraphBase;
alpar@1555
   434
deba@1566
   435
  /// \ingroup graphs
deba@1566
   436
  ///
deba@1566
   437
  /// \brief An undirected full graph class.
deba@1566
   438
  ///
deba@1726
   439
  /// This is a simple and fast undirected full graph implementation.
deba@1566
   440
  /// It is completely static, so you can neither add nor delete either
deba@1566
   441
  /// edges or nodes.
deba@1566
   442
  ///
klao@1909
   443
  /// The main difference beetween the \e FullGraph and \e FullUGraph class
deba@1566
   444
  /// is that this class conforms to the undirected graph concept and
deba@1726
   445
  /// it does not contain the loop edges.
deba@1566
   446
  ///
deba@1986
   447
  /// \sa FullUGraphBase
deba@1566
   448
  /// \sa FullGraph
deba@1566
   449
  ///
deba@1566
   450
  /// \author Balazs Dezso
klao@1909
   451
  class FullUGraph : public ExtendedFullUGraphBase {
deba@1566
   452
  public:
deba@1979
   453
deba@1979
   454
    typedef ExtendedFullUGraphBase Parent;
deba@1979
   455
deba@1979
   456
    /// \brief Constructor
deba@1987
   457
    FullUGraph() { construct(0); }
deba@1987
   458
deba@1987
   459
    /// \brief Constructor
klao@1909
   460
    FullUGraph(int n) { construct(n); }
deba@1979
   461
deba@1979
   462
    /// \brief Resize the graph
deba@1979
   463
    ///
deba@1986
   464
    /// Resize the graph. The function will fully destroy and build the graph.
deba@1986
   465
    /// This cause that the maps of the graph will reallocated
deba@1986
   466
    /// automatically and the previous values will be lost.
deba@1979
   467
    void resize(int n) {
deba@1979
   468
      Parent::getNotifier(Edge()).clear();
deba@1979
   469
      Parent::getNotifier(UEdge()).clear();
deba@1979
   470
      Parent::getNotifier(Node()).clear();
deba@1979
   471
      construct(n);
deba@1979
   472
      Parent::getNotifier(Node()).build();
deba@1979
   473
      Parent::getNotifier(UEdge()).build();
deba@1979
   474
      Parent::getNotifier(Edge()).build();
deba@1979
   475
    }
deba@1566
   476
  };
alpar@591
   477
deba@1820
   478
deba@1910
   479
  class FullBpUGraphBase {
deba@1820
   480
  protected:
deba@1820
   481
deba@1910
   482
    int _aNodeNum;
deba@1910
   483
    int _bNodeNum;
deba@1820
   484
deba@1820
   485
    int _edgeNum;
deba@1820
   486
deba@1820
   487
  public:
deba@1820
   488
deba@1820
   489
    class NodeSetError : public LogicError {
deba@1820
   490
      virtual const char* exceptionName() const { 
deba@1910
   491
	return "lemon::FullBpUGraph::NodeSetError";
deba@1820
   492
      }
deba@1820
   493
    };
deba@1820
   494
  
deba@1820
   495
    class Node {
deba@1910
   496
      friend class FullBpUGraphBase;
deba@1820
   497
    protected:
deba@1820
   498
      int id;
deba@1820
   499
deba@1820
   500
      Node(int _id) : id(_id) {}
deba@1820
   501
    public:
deba@1820
   502
      Node() {}
deba@1820
   503
      Node(Invalid) { id = -1; }
deba@1820
   504
      bool operator==(const Node i) const {return id==i.id;}
deba@1820
   505
      bool operator!=(const Node i) const {return id!=i.id;}
deba@1820
   506
      bool operator<(const Node i) const {return id<i.id;}
deba@1820
   507
    };
deba@1820
   508
deba@1820
   509
    class Edge {
deba@1910
   510
      friend class FullBpUGraphBase;
deba@1820
   511
    protected:
deba@1820
   512
      int id;
deba@1820
   513
deba@1820
   514
      Edge(int _id) { id = _id;}
deba@1820
   515
    public:
deba@1820
   516
      Edge() {}
deba@1820
   517
      Edge (Invalid) { id = -1; }
deba@1820
   518
      bool operator==(const Edge i) const {return id==i.id;}
deba@1820
   519
      bool operator!=(const Edge i) const {return id!=i.id;}
deba@1820
   520
      bool operator<(const Edge i) const {return id<i.id;}
deba@1820
   521
    };
deba@1820
   522
deba@1910
   523
    void construct(int aNodeNum, int bNodeNum) {
deba@1910
   524
      _aNodeNum = aNodeNum;
deba@1910
   525
      _bNodeNum = bNodeNum;
deba@1910
   526
      _edgeNum = aNodeNum * bNodeNum;
deba@1820
   527
    }
deba@1820
   528
deba@1910
   529
    void firstANode(Node& node) const {
deba@1910
   530
      node.id = 2 * _aNodeNum - 2;
deba@1820
   531
      if (node.id < 0) node.id = -1; 
deba@1820
   532
    }
deba@1910
   533
    void nextANode(Node& node) const {
deba@1820
   534
      node.id -= 2;
deba@1820
   535
      if (node.id < 0) node.id = -1; 
deba@1820
   536
    }
deba@1820
   537
deba@1910
   538
    void firstBNode(Node& node) const {
deba@1910
   539
      node.id = 2 * _bNodeNum - 1;
deba@1820
   540
    }
deba@1910
   541
    void nextBNode(Node& node) const {
deba@1820
   542
      node.id -= 2;
deba@1820
   543
    }
deba@1820
   544
deba@1820
   545
    void first(Node& node) const {
deba@1910
   546
      if (_aNodeNum > 0) {
deba@1910
   547
	node.id = 2 * _aNodeNum - 2;
deba@1820
   548
      } else {
deba@1910
   549
	node.id = 2 * _bNodeNum - 1;
deba@1820
   550
      }
deba@1820
   551
    }
deba@1820
   552
    void next(Node& node) const {
deba@1820
   553
      node.id -= 2;
deba@1820
   554
      if (node.id == -2) {
deba@1910
   555
	node.id = 2 * _bNodeNum - 1;
deba@1820
   556
      }
deba@1820
   557
    }
deba@1820
   558
  
deba@1820
   559
    void first(Edge& edge) const {
deba@1820
   560
      edge.id = _edgeNum - 1;
deba@1820
   561
    }
deba@1820
   562
    void next(Edge& edge) const {
deba@1820
   563
      --edge.id;
deba@1820
   564
    }
deba@1820
   565
deba@1910
   566
    void firstOut(Edge& edge, const Node& node) const {
deba@1820
   567
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@1910
   568
      edge.id = (node.id >> 1) * _bNodeNum;
deba@1820
   569
    }
deba@1910
   570
    void nextOut(Edge& edge) const {
deba@1820
   571
      ++(edge.id);
deba@1910
   572
      if (edge.id % _bNodeNum == 0) edge.id = -1;
deba@1820
   573
    }
deba@1820
   574
deba@1910
   575
    void firstIn(Edge& edge, const Node& node) const {
deba@1820
   576
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@1820
   577
      edge.id = (node.id >> 1);
deba@1820
   578
    }
deba@1910
   579
    void nextIn(Edge& edge) const {
deba@1910
   580
      edge.id += _bNodeNum;
deba@1820
   581
      if (edge.id >= _edgeNum) edge.id = -1;
deba@1820
   582
    }
deba@1820
   583
deba@1820
   584
    static int id(const Node& node) {
deba@1820
   585
      return node.id;
deba@1820
   586
    }
deba@1820
   587
    static Node nodeFromId(int id) {
deba@1820
   588
      return Node(id);
deba@1820
   589
    }
deba@1820
   590
    int maxNodeId() const {
deba@1910
   591
      return _aNodeNum > _bNodeNum ? 
deba@1910
   592
	_aNodeNum * 2 - 2 : _bNodeNum * 2 - 1;
deba@1820
   593
    }
deba@1820
   594
  
deba@1820
   595
    static int id(const Edge& edge) {
deba@1820
   596
      return edge.id;
deba@1820
   597
    }
deba@1820
   598
    static Edge edgeFromId(int id) {
deba@1820
   599
      return Edge(id);
deba@1820
   600
    }
deba@1820
   601
    int maxEdgeId() const {
deba@1820
   602
      return _edgeNum - 1;
deba@1820
   603
    }
deba@1820
   604
  
deba@1910
   605
    static int aNodeId(const Node& node) {
deba@1820
   606
      return node.id >> 1;
deba@1820
   607
    }
deba@1995
   608
    static Node fromANodeId(int id) {
deba@1820
   609
      return Node(id << 1);
deba@1820
   610
    }
deba@1910
   611
    int maxANodeId() const {
deba@1910
   612
      return _aNodeNum;
deba@1820
   613
    }
deba@1820
   614
deba@1910
   615
    static int bNodeId(const Node& node) {
deba@1820
   616
      return node.id >> 1;
deba@1820
   617
    }
deba@1910
   618
    static Node fromBNodeId(int id) {
deba@1820
   619
      return Node((id << 1) + 1);
deba@1820
   620
    }
deba@1910
   621
    int maxBNodeId() const {
deba@1910
   622
      return _bNodeNum;
deba@1820
   623
    }
deba@1820
   624
deba@1910
   625
    Node aNode(const Edge& edge) const {
deba@1910
   626
      return Node((edge.id / _bNodeNum) << 1);
deba@1820
   627
    }
deba@1910
   628
    Node bNode(const Edge& edge) const {
deba@1910
   629
      return Node(((edge.id % _bNodeNum) << 1) + 1);
deba@1820
   630
    }
deba@1820
   631
deba@1910
   632
    static bool aNode(const Node& node) {
deba@1820
   633
      return (node.id & 1) == 0;
deba@1820
   634
    }
deba@1820
   635
deba@1910
   636
    static bool bNode(const Node& node) {
deba@1820
   637
      return (node.id & 1) == 1;
deba@1820
   638
    }
deba@1820
   639
deba@1910
   640
    static Node aNode(int index) {
deba@1820
   641
      return Node(index << 1);
deba@1820
   642
    }
deba@1820
   643
deba@1910
   644
    static Node bNode(int index) {
deba@1820
   645
      return Node((index << 1) + 1);
deba@1820
   646
    }
deba@1820
   647
deba@2031
   648
    typedef True NodeNumTag;
deba@2031
   649
    int nodeNum() const { return _aNodeNum + _bNodeNum; }
deba@2031
   650
    int aNodeNum() const { return _aNodeNum; }
deba@2031
   651
    int bNodeNum() const { return _bNodeNum; }
deba@2031
   652
deba@2031
   653
    typedef True EdgeNumTag;
deba@2031
   654
    int edgeNum() const { return _edgeNum; }
deba@2031
   655
deba@1820
   656
  };
deba@1820
   657
deba@1820
   658
deba@1979
   659
  typedef BpUGraphExtender< BpUGraphBaseExtender<
deba@1979
   660
    FullBpUGraphBase> > ExtendedFullBpUGraphBase;
deba@1820
   661
deba@1820
   662
deba@1910
   663
  /// \ingroup graphs
deba@1910
   664
  ///
deba@1910
   665
  /// \brief An undirected full bipartite graph class.
deba@1910
   666
  ///
deba@1910
   667
  /// This is a simple and fast bipartite undirected full graph implementation.
deba@1910
   668
  /// It is completely static, so you can neither add nor delete either
deba@1910
   669
  /// edges or nodes.
deba@1910
   670
  ///
deba@1986
   671
  /// \sa FullUGraphBase
deba@1910
   672
  /// \sa FullGraph
deba@1910
   673
  ///
deba@1910
   674
  /// \author Balazs Dezso
deba@1910
   675
  class FullBpUGraph : 
deba@1910
   676
    public ExtendedFullBpUGraphBase {
deba@1820
   677
  public:
deba@1979
   678
deba@1910
   679
    typedef ExtendedFullBpUGraphBase Parent;
deba@1979
   680
deba@1987
   681
    FullBpUGraph() {
deba@1987
   682
      Parent::construct(0, 0);
deba@1987
   683
    }
deba@1987
   684
deba@1910
   685
    FullBpUGraph(int aNodeNum, int bNodeNum) {
deba@1910
   686
      Parent::construct(aNodeNum, bNodeNum);
deba@1820
   687
    }
deba@1987
   688
deba@1979
   689
    /// \brief Resize the graph
deba@1979
   690
    ///
deba@1979
   691
    void resize(int n, int m) {
deba@1979
   692
      Parent::getNotifier(Edge()).clear();
deba@1979
   693
      Parent::getNotifier(UEdge()).clear();
deba@1979
   694
      Parent::getNotifier(Node()).clear();
deba@1987
   695
      Parent::getNotifier(ANode()).clear();
deba@1987
   696
      Parent::getNotifier(BNode()).clear();
deba@1979
   697
      construct(n, m);
deba@1987
   698
      Parent::getNotifier(ANode()).build();
deba@1987
   699
      Parent::getNotifier(BNode()).build();
deba@1979
   700
      Parent::getNotifier(Node()).build();
deba@1979
   701
      Parent::getNotifier(UEdge()).build();
deba@1979
   702
      Parent::getNotifier(Edge()).build();
deba@1979
   703
    }
deba@1820
   704
  };
deba@1820
   705
alpar@921
   706
} //namespace lemon
alpar@591
   707
alpar@591
   708
alpar@921
   709
#endif //LEMON_FULL_GRAPH_H