/* -*- mode: C++; indent-tabs-mode: nil; -*- * * This file is a part of LEMON, a generic C++ optimization library. * * Copyright (C) 2003-2013 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_FULL_GRAPH_H #define LEMON_FULL_GRAPH_H #include #include ///\ingroup graphs ///\file ///\brief FullDigraph and FullGraph classes. namespace lemon { class FullDigraphBase { public: typedef FullDigraphBase Digraph; class Node; class Arc; protected: int _node_num; int _arc_num; FullDigraphBase() {} void construct(int n) { _node_num = n; _arc_num = n * n; } public: typedef True NodeNumTag; typedef True ArcNumTag; Node operator()(int ix) const { return Node(ix); } static int index(const Node& node) { return node._id; } Arc arc(const Node& s, const Node& t) const { return Arc(s._id * _node_num + t._id); } int nodeNum() const { return _node_num; } int arcNum() const { return _arc_num; } int maxNodeId() const { return _node_num - 1; } int maxArcId() const { return _arc_num - 1; } Node source(Arc arc) const { return arc._id / _node_num; } Node target(Arc arc) const { return arc._id % _node_num; } static int id(Node node) { return node._id; } static int id(Arc arc) { return arc._id; } static Node nodeFromId(int id) { return Node(id);} static Arc arcFromId(int id) { return Arc(id);} typedef True FindArcTag; Arc findArc(Node s, Node t, Arc prev = INVALID) const { return prev == INVALID ? arc(s, t) : INVALID; } class Node { friend class FullDigraphBase; protected: int _id; Node(int id) : _id(id) {} public: Node() {} Node (Invalid) : _id(-1) {} bool operator==(const Node node) const {return _id == node._id;} bool operator!=(const Node node) const {return _id != node._id;} bool operator<(const Node node) const {return _id < node._id;} }; class Arc { friend class FullDigraphBase; protected: int _id; // _node_num * source + target; Arc(int id) : _id(id) {} public: Arc() { } Arc (Invalid) { _id = -1; } bool operator==(const Arc arc) const {return _id == arc._id;} bool operator!=(const Arc arc) const {return _id != arc._id;} bool operator<(const Arc arc) const {return _id < arc._id;} }; void first(Node& node) const { node._id = _node_num - 1; } static void next(Node& node) { --node._id; } void first(Arc& arc) const { arc._id = _arc_num - 1; } static void next(Arc& arc) { --arc._id; } void firstOut(Arc& arc, const Node& node) const { arc._id = (node._id + 1) * _node_num - 1; } void nextOut(Arc& arc) const { if (arc._id % _node_num == 0) arc._id = 0; --arc._id; } void firstIn(Arc& arc, const Node& node) const { arc._id = _arc_num + node._id - _node_num; } void nextIn(Arc& arc) const { arc._id -= _node_num; if (arc._id < 0) arc._id = -1; } }; typedef DigraphExtender ExtendedFullDigraphBase; /// \ingroup graphs /// /// \brief A directed full graph class. /// /// FullDigraph is a simple and fast implmenetation of directed full /// (complete) graphs. It contains an arc from each node to each node /// (including a loop for each node), therefore the number of arcs /// is the square of the number of nodes. /// This class is completely static and it needs constant memory space. /// Thus you can neither add nor delete nodes or arcs, however /// the structure can be resized using resize(). /// /// This type fully conforms to the \ref concepts::Digraph "Digraph concept". /// Most of its member functions and nested classes are documented /// only in the concept class. /// /// This class provides constant time counting for nodes and arcs. /// /// \note FullDigraph and FullGraph classes are very similar, /// but there are two differences. While this class conforms only /// to the \ref concepts::Digraph "Digraph" concept, FullGraph /// conforms to the \ref concepts::Graph "Graph" concept, /// moreover FullGraph does not contain a loop for each /// node as this class does. /// /// \sa FullGraph class FullDigraph : public ExtendedFullDigraphBase { typedef ExtendedFullDigraphBase Parent; public: /// \brief Default constructor. /// /// Default constructor. The number of nodes and arcs will be zero. FullDigraph() { construct(0); } /// \brief Constructor /// /// Constructor. /// \param n The number of the nodes. FullDigraph(int n) { construct(n); } /// \brief Resizes the digraph /// /// This function resizes the digraph. It fully destroys and /// rebuilds the structure, therefore the maps of the digraph will be /// reallocated automatically and the previous values will be lost. void resize(int n) { Parent::notifier(Arc()).clear(); Parent::notifier(Node()).clear(); construct(n); Parent::notifier(Node()).build(); Parent::notifier(Arc()).build(); } /// \brief Returns the node with the given index. /// /// Returns the node with the given index. Since this structure is /// completely static, the nodes can be indexed with integers from /// the range [0..nodeNum()-1]. /// The index of a node is the same as its ID. /// \sa index() Node operator()(int ix) const { return Parent::operator()(ix); } /// \brief Returns the index of the given node. /// /// Returns the index of the given node. Since this structure is /// completely static, the nodes can be indexed with integers from /// the range [0..nodeNum()-1]. /// The index of a node is the same as its ID. /// \sa operator()() static int index(const Node& node) { return Parent::index(node); } /// \brief Returns the arc connecting the given nodes. /// /// Returns the arc connecting the given nodes. Arc arc(Node u, Node v) const { return Parent::arc(u, v); } /// \brief Number of nodes. int nodeNum() const { return Parent::nodeNum(); } /// \brief Number of arcs. int arcNum() const { return Parent::arcNum(); } }; class FullGraphBase { public: typedef FullGraphBase Graph; class Node; class Arc; class Edge; protected: int _node_num; int _edge_num; FullGraphBase() {} void construct(int n) { _node_num = n; _edge_num = n * (n - 1) / 2; } int _uid(int e) const { int u = e / _node_num; int v = e % _node_num; return u < v ? u : _node_num - 2 - u; } int _vid(int e) const { int u = e / _node_num; int v = e % _node_num; return u < v ? v : _node_num - 1 - v; } void _uvid(int e, int& u, int& v) const { u = e / _node_num; v = e % _node_num; if (u >= v) { u = _node_num - 2 - u; v = _node_num - 1 - v; } } void _stid(int a, int& s, int& t) const { if ((a & 1) == 1) { _uvid(a >> 1, s, t); } else { _uvid(a >> 1, t, s); } } int _eid(int u, int v) const { if (u < (_node_num - 1) / 2) { return u * _node_num + v; } else { return (_node_num - 1 - u) * _node_num - v - 1; } } public: Node operator()(int ix) const { return Node(ix); } static int index(const Node& node) { return node._id; } Edge edge(const Node& u, const Node& v) const { if (u._id < v._id) { return Edge(_eid(u._id, v._id)); } else if (u._id != v._id) { return Edge(_eid(v._id, u._id)); } else { return INVALID; } } Arc arc(const Node& s, const Node& t) const { if (s._id < t._id) { return Arc((_eid(s._id, t._id) << 1) | 1); } else if (s._id != t._id) { return Arc(_eid(t._id, s._id) << 1); } else { return INVALID; } } typedef True NodeNumTag; typedef True ArcNumTag; typedef True EdgeNumTag; int nodeNum() const { return _node_num; } int arcNum() const { return 2 * _edge_num; } int edgeNum() const { return _edge_num; } static int id(Node node) { return node._id; } static int id(Arc arc) { return arc._id; } static int id(Edge edge) { return edge._id; } int maxNodeId() const { return _node_num-1; } int maxArcId() const { return 2 * _edge_num-1; } int maxEdgeId() const { return _edge_num-1; } static Node nodeFromId(int id) { return Node(id);} static Arc arcFromId(int id) { return Arc(id);} static Edge edgeFromId(int id) { return Edge(id);} Node u(Edge edge) const { return Node(_uid(edge._id)); } Node v(Edge edge) const { return Node(_vid(edge._id)); } Node source(Arc arc) const { return Node((arc._id & 1) == 1 ? _uid(arc._id >> 1) : _vid(arc._id >> 1)); } Node target(Arc arc) const { return Node((arc._id & 1) == 1 ? _vid(arc._id >> 1) : _uid(arc._id >> 1)); } typedef True FindEdgeTag; typedef True FindArcTag; Edge findEdge(Node u, Node v, Edge prev = INVALID) const { return prev != INVALID ? INVALID : edge(u, v); } Arc findArc(Node s, Node t, Arc prev = INVALID) const { return prev != INVALID ? INVALID : arc(s, t); } class Node { friend class FullGraphBase; protected: int _id; Node(int id) : _id(id) {} public: Node() {} Node (Invalid) { _id = -1; } bool operator==(const Node node) const {return _id == node._id;} bool operator!=(const Node node) const {return _id != node._id;} bool operator<(const Node node) const {return _id < node._id;} }; class Edge { friend class FullGraphBase; friend class Arc; protected: int _id; Edge(int id) : _id(id) {} public: Edge() { } Edge (Invalid) { _id = -1; } bool operator==(const Edge edge) const {return _id == edge._id;} bool operator!=(const Edge edge) const {return _id != edge._id;} bool operator<(const Edge edge) const {return _id < edge._id;} }; class Arc { friend class FullGraphBase; protected: int _id; Arc(int id) : _id(id) {} public: Arc() { } Arc (Invalid) { _id = -1; } operator Edge() const { return Edge(_id != -1 ? (_id >> 1) : -1); } bool operator==(const Arc arc) const {return _id == arc._id;} bool operator!=(const Arc arc) const {return _id != arc._id;} bool operator<(const Arc arc) const {return _id < arc._id;} }; static bool direction(Arc arc) { return (arc._id & 1) == 1; } static Arc direct(Edge edge, bool dir) { return Arc((edge._id << 1) | (dir ? 1 : 0)); } void first(Node& node) const { node._id = _node_num - 1; } static void next(Node& node) { --node._id; } void first(Arc& arc) const { arc._id = (_edge_num << 1) - 1; } static void next(Arc& arc) { --arc._id; } void first(Edge& edge) const { edge._id = _edge_num - 1; } static void next(Edge& edge) { --edge._id; } void firstOut(Arc& arc, const Node& node) const { int s = node._id, t = _node_num - 1; if (s < t) { arc._id = (_eid(s, t) << 1) | 1; } else { --t; arc._id = (t != -1 ? (_eid(t, s) << 1) : -1); } } void nextOut(Arc& arc) const { int s, t; _stid(arc._id, s, t); --t; if (s < t) { arc._id = (_eid(s, t) << 1) | 1; } else { if (s == t) --t; arc._id = (t != -1 ? (_eid(t, s) << 1) : -1); } } void firstIn(Arc& arc, const Node& node) const { int s = _node_num - 1, t = node._id; if (s > t) { arc._id = (_eid(t, s) << 1); } else { --s; arc._id = (s != -1 ? (_eid(s, t) << 1) | 1 : -1); } } void nextIn(Arc& arc) const { int s, t; _stid(arc._id, s, t); --s; if (s > t) { arc._id = (_eid(t, s) << 1); } else { if (s == t) --s; arc._id = (s != -1 ? (_eid(s, t) << 1) | 1 : -1); } } void firstInc(Edge& edge, bool& dir, const Node& node) const { int u = node._id, v = _node_num - 1; if (u < v) { edge._id = _eid(u, v); dir = true; } else { --v; edge._id = (v != -1 ? _eid(v, u) : -1); dir = false; } } void nextInc(Edge& edge, bool& dir) const { int u, v; if (dir) { _uvid(edge._id, u, v); --v; if (u < v) { edge._id = _eid(u, v); } else { --v; edge._id = (v != -1 ? _eid(v, u) : -1); dir = false; } } else { _uvid(edge._id, v, u); --v; edge._id = (v != -1 ? _eid(v, u) : -1); } } }; typedef GraphExtender ExtendedFullGraphBase; /// \ingroup graphs /// /// \brief An undirected full graph class. /// /// FullGraph is a simple and fast implmenetation of undirected full /// (complete) graphs. It contains an edge between every distinct pair /// of nodes, therefore the number of edges is n(n-1)/2. /// This class is completely static and it needs constant memory space. /// Thus you can neither add nor delete nodes or edges, however /// the structure can be resized using resize(). /// /// This type fully conforms to the \ref concepts::Graph "Graph concept". /// Most of its member functions and nested classes are documented /// only in the concept class. /// /// This class provides constant time counting for nodes, edges and arcs. /// /// \note FullDigraph and FullGraph classes are very similar, /// but there are two differences. While FullDigraph /// conforms only to the \ref concepts::Digraph "Digraph" concept, /// this class conforms to the \ref concepts::Graph "Graph" concept, /// moreover this class does not contain a loop for each /// node as FullDigraph does. /// /// \sa FullDigraph class FullGraph : public ExtendedFullGraphBase { typedef ExtendedFullGraphBase Parent; public: /// \brief Default constructor. /// /// Default constructor. The number of nodes and edges will be zero. FullGraph() { construct(0); } /// \brief Constructor /// /// Constructor. /// \param n The number of the nodes. FullGraph(int n) { construct(n); } /// \brief Resizes the graph /// /// This function resizes the graph. It fully destroys and /// rebuilds the structure, therefore the maps of the graph will be /// reallocated automatically and the previous values will be lost. void resize(int n) { Parent::notifier(Arc()).clear(); Parent::notifier(Edge()).clear(); Parent::notifier(Node()).clear(); construct(n); Parent::notifier(Node()).build(); Parent::notifier(Edge()).build(); Parent::notifier(Arc()).build(); } /// \brief Returns the node with the given index. /// /// Returns the node with the given index. Since this structure is /// completely static, the nodes can be indexed with integers from /// the range [0..nodeNum()-1]. /// The index of a node is the same as its ID. /// \sa index() Node operator()(int ix) const { return Parent::operator()(ix); } /// \brief Returns the index of the given node. /// /// Returns the index of the given node. Since this structure is /// completely static, the nodes can be indexed with integers from /// the range [0..nodeNum()-1]. /// The index of a node is the same as its ID. /// \sa operator()() static int index(const Node& node) { return Parent::index(node); } /// \brief Returns the arc connecting the given nodes. /// /// Returns the arc connecting the given nodes. Arc arc(Node s, Node t) const { return Parent::arc(s, t); } /// \brief Returns the edge connecting the given nodes. /// /// Returns the edge connecting the given nodes. Edge edge(Node u, Node v) const { return Parent::edge(u, v); } /// \brief Number of nodes. int nodeNum() const { return Parent::nodeNum(); } /// \brief Number of arcs. int arcNum() const { return Parent::arcNum(); } /// \brief Number of edges. int edgeNum() const { return Parent::edgeNum(); } }; class FullBpGraphBase { protected: int _red_num, _blue_num; int _node_num, _edge_num; public: typedef FullBpGraphBase Graph; class Node; class Arc; class Edge; class Node { friend class FullBpGraphBase; protected: int _id; explicit Node(int id) { _id = id;} public: Node() {} Node (Invalid) { _id = -1; } bool operator==(const Node& node) const {return _id == node._id;} bool operator!=(const Node& node) const {return _id != node._id;} bool operator<(const Node& node) const {return _id < node._id;} }; class RedNode : public Node { friend class FullBpGraphBase; protected: explicit RedNode(int pid) : Node(pid) {} public: RedNode() {} RedNode(const RedNode& node) : Node(node) {} RedNode(Invalid) : Node(INVALID){} }; class BlueNode : public Node { friend class FullBpGraphBase; protected: explicit BlueNode(int pid) : Node(pid) {} public: BlueNode() {} BlueNode(const BlueNode& node) : Node(node) {} BlueNode(Invalid) : Node(INVALID){} }; class Edge { friend class FullBpGraphBase; protected: int _id; explicit Edge(int id) { _id = id;} public: Edge() {} Edge (Invalid) { _id = -1; } bool operator==(const Edge& arc) const {return _id == arc._id;} bool operator!=(const Edge& arc) const {return _id != arc._id;} bool operator<(const Edge& arc) const {return _id < arc._id;} }; class Arc { friend class FullBpGraphBase; protected: int _id; explicit Arc(int id) { _id = id;} public: operator Edge() const { return _id != -1 ? edgeFromId(_id / 2) : INVALID; } Arc() {} Arc (Invalid) { _id = -1; } bool operator==(const Arc& arc) const {return _id == arc._id;} bool operator!=(const Arc& arc) const {return _id != arc._id;} bool operator<(const Arc& arc) const {return _id < arc._id;} }; protected: FullBpGraphBase() : _red_num(0), _blue_num(0), _node_num(0), _edge_num(0) {} void construct(int redNum, int blueNum) { _red_num = redNum; _blue_num = blueNum; _node_num = redNum + blueNum; _edge_num = redNum * blueNum; } public: typedef True NodeNumTag; typedef True EdgeNumTag; typedef True ArcNumTag; int nodeNum() const { return _node_num; } int redNum() const { return _red_num; } int blueNum() const { return _blue_num; } int edgeNum() const { return _edge_num; } int arcNum() const { return 2 * _edge_num; } int maxNodeId() const { return _node_num - 1; } int maxRedId() const { return _red_num - 1; } int maxBlueId() const { return _blue_num - 1; } int maxEdgeId() const { return _edge_num - 1; } int maxArcId() const { return 2 * _edge_num - 1; } bool red(Node n) const { return n._id < _red_num; } bool blue(Node n) const { return n._id >= _red_num; } static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); } static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); } Node source(Arc a) const { if (a._id & 1) { return Node((a._id >> 1) % _red_num); } else { return Node((a._id >> 1) / _red_num + _red_num); } } Node target(Arc a) const { if (a._id & 1) { return Node((a._id >> 1) / _red_num + _red_num); } else { return Node((a._id >> 1) % _red_num); } } RedNode redNode(Edge e) const { return RedNode(e._id % _red_num); } BlueNode blueNode(Edge e) const { return BlueNode(e._id / _red_num + _red_num); } static bool direction(Arc a) { return (a._id & 1) == 1; } static Arc direct(Edge e, bool d) { return Arc(e._id * 2 + (d ? 1 : 0)); } void first(Node& node) const { node._id = _node_num - 1; } static void next(Node& node) { --node._id; } void first(RedNode& node) const { node._id = _red_num - 1; } static void next(RedNode& node) { --node._id; } void first(BlueNode& node) const { if (_red_num == _node_num) node._id = -1; else node._id = _node_num - 1; } void next(BlueNode& node) const { if (node._id == _red_num) node._id = -1; else --node._id; } void first(Arc& arc) const { arc._id = 2 * _edge_num - 1; } static void next(Arc& arc) { --arc._id; } void first(Edge& arc) const { arc._id = _edge_num - 1; } static void next(Edge& arc) { --arc._id; } void firstOut(Arc &a, const Node& v) const { if (v._id < _red_num) { a._id = 2 * (v._id + _red_num * (_blue_num - 1)) + 1; } else { a._id = 2 * (_red_num - 1 + _red_num * (v._id - _red_num)); } } void nextOut(Arc &a) const { if (a._id & 1) { a._id -= 2 * _red_num; if (a._id < 0) a._id = -1; } else { if (a._id % (2 * _red_num) == 0) a._id = -1; else a._id -= 2; } } void firstIn(Arc &a, const Node& v) const { if (v._id < _red_num) { a._id = 2 * (v._id + _red_num * (_blue_num - 1)); } else { a._id = 2 * (_red_num - 1 + _red_num * (v._id - _red_num)) + 1; } } void nextIn(Arc &a) const { if (a._id & 1) { if (a._id % (2 * _red_num) == 1) a._id = -1; else a._id -= 2; } else { a._id -= 2 * _red_num; if (a._id < 0) a._id = -1; } } void firstInc(Edge &e, bool& d, const Node& v) const { if (v._id < _red_num) { d = true; e._id = v._id + _red_num * (_blue_num - 1); } else { d = false; e._id = _red_num - 1 + _red_num * (v._id - _red_num); } } void nextInc(Edge &e, bool& d) const { if (d) { e._id -= _red_num; if (e._id < 0) e._id = -1; } else { if (e._id % _red_num == 0) e._id = -1; else --e._id; } } static int id(const Node& v) { return v._id; } int id(const RedNode& v) const { return v._id; } int id(const BlueNode& v) const { return v._id - _red_num; } static int id(Arc e) { return e._id; } static int id(Edge e) { return e._id; } static Node nodeFromId(int id) { return Node(id);} static Arc arcFromId(int id) { return Arc(id);} static Edge edgeFromId(int id) { return Edge(id);} bool valid(Node n) const { return n._id >= 0 && n._id < _node_num; } bool valid(Arc a) const { return a._id >= 0 && a._id < 2 * _edge_num; } bool valid(Edge e) const { return e._id >= 0 && e._id < _edge_num; } RedNode redNode(int index) const { return RedNode(index); } int index(RedNode n) const { return n._id; } BlueNode blueNode(int index) const { return BlueNode(index + _red_num); } int index(BlueNode n) const { return n._id - _red_num; } void clear() { _red_num = 0; _blue_num = 0; _node_num = 0; _edge_num = 0; } Edge edge(const Node& u, const Node& v) const { if (u._id < _red_num) { if (v._id < _red_num) { return Edge(-1); } else { return Edge(u._id + _red_num * (v._id - _red_num)); } } else { if (v._id < _red_num) { return Edge(v._id + _red_num * (u._id - _red_num)); } else { return Edge(-1); } } } Arc arc(const Node& u, const Node& v) const { if (u._id < _red_num) { if (v._id < _red_num) { return Arc(-1); } else { return Arc(2 * (u._id + _red_num * (v._id - _red_num)) + 1); } } else { if (v._id < _red_num) { return Arc(2 * (v._id + _red_num * (u._id - _red_num))); } else { return Arc(-1); } } } typedef True FindEdgeTag; typedef True FindArcTag; Edge findEdge(Node u, Node v, Edge prev = INVALID) const { return prev != INVALID ? INVALID : edge(u, v); } Arc findArc(Node s, Node t, Arc prev = INVALID) const { return prev != INVALID ? INVALID : arc(s, t); } }; typedef BpGraphExtender ExtendedFullBpGraphBase; /// \ingroup graphs /// /// \brief An undirected full bipartite graph class. /// /// FullBpGraph is a simple and fast implmenetation of undirected /// full bipartite graphs. It contains an edge between every /// red-blue pairs of nodes, therefore the number of edges is /// nr*nb. This class is completely static and it needs /// constant memory space. Thus you can neither add nor delete /// nodes or edges, however the structure can be resized using /// resize(). /// /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept". /// Most of its member functions and nested classes are documented /// only in the concept class. /// /// This class provides constant time counting for nodes, edges and arcs. /// /// \sa FullGraph class FullBpGraph : public ExtendedFullBpGraphBase { public: typedef ExtendedFullBpGraphBase Parent; /// \brief Default constructor. /// /// Default constructor. The number of nodes and edges will be zero. FullBpGraph() { construct(0, 0); } /// \brief Constructor /// /// Constructor. /// \param redNum The number of the red nodes. /// \param blueNum The number of the blue nodes. FullBpGraph(int redNum, int blueNum) { construct(redNum, blueNum); } /// \brief Resizes the graph /// /// This function resizes the graph. It fully destroys and /// rebuilds the structure, therefore the maps of the graph will be /// reallocated automatically and the previous values will be lost. void resize(int redNum, int blueNum) { Parent::notifier(Arc()).clear(); Parent::notifier(Edge()).clear(); Parent::notifier(Node()).clear(); Parent::notifier(BlueNode()).clear(); Parent::notifier(RedNode()).clear(); construct(redNum, blueNum); Parent::notifier(RedNode()).build(); Parent::notifier(BlueNode()).build(); Parent::notifier(Node()).build(); Parent::notifier(Edge()).build(); Parent::notifier(Arc()).build(); } using Parent::redNode; using Parent::blueNode; /// \brief Returns the red node with the given index. /// /// Returns the red node with the given index. Since this /// structure is completely static, the red nodes can be indexed /// with integers from the range [0..redNum()-1]. /// \sa redIndex() RedNode redNode(int index) const { return Parent::redNode(index); } /// \brief Returns the index of the given red node. /// /// Returns the index of the given red node. Since this structure /// is completely static, the red nodes can be indexed with /// integers from the range [0..redNum()-1]. /// /// \sa operator()() int index(RedNode node) const { return Parent::index(node); } /// \brief Returns the blue node with the given index. /// /// Returns the blue node with the given index. Since this /// structure is completely static, the blue nodes can be indexed /// with integers from the range [0..blueNum()-1]. /// \sa blueIndex() BlueNode blueNode(int index) const { return Parent::blueNode(index); } /// \brief Returns the index of the given blue node. /// /// Returns the index of the given blue node. Since this structure /// is completely static, the blue nodes can be indexed with /// integers from the range [0..blueNum()-1]. /// /// \sa operator()() int index(BlueNode node) const { return Parent::index(node); } /// \brief Returns the edge which connects the given nodes. /// /// Returns the edge which connects the given nodes. Edge edge(const Node& u, const Node& v) const { return Parent::edge(u, v); } /// \brief Returns the arc which connects the given nodes. /// /// Returns the arc which connects the given nodes. Arc arc(const Node& u, const Node& v) const { return Parent::arc(u, v); } /// \brief Number of nodes. int nodeNum() const { return Parent::nodeNum(); } /// \brief Number of red nodes. int redNum() const { return Parent::redNum(); } /// \brief Number of blue nodes. int blueNum() const { return Parent::blueNum(); } /// \brief Number of arcs. int arcNum() const { return Parent::arcNum(); } /// \brief Number of edges. int edgeNum() const { return Parent::edgeNum(); } }; } //namespace lemon #endif //LEMON_FULL_GRAPH_H