lemon/full_graph.h
author alpar
Fri, 13 Oct 2006 15:10:50 +0000
changeset 2241 37e0966e43b6
parent 2223 590c1b663a27
child 2256 b22dfb6c5ff3
permissions -rw-r--r--
Improve build environment and scripts
     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