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