lemon/full_graph.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2223 590c1b663a27
child 2256 b22dfb6c5ff3
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

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