Serious bugfix.
3 * lemon/undir_graph_extender.h - Part of LEMON, a generic C++
6 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
7 * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
10 * Permission to use, modify and distribute this software is granted
11 * provided that this copyright notice appears in all copies. For
12 * precise terms see the accompanying LICENSE file.
14 * This software is provided "AS IS" with no warranty of any kind,
15 * express or implied, and with no claim as to its suitability for any
20 #ifndef LEMON_UNDIR_GRAPH_EXTENDER_H
21 #define LEMON_UNDIR_GRAPH_EXTENDER_H
23 #include <lemon/invalid.h>
27 template <typename _Base>
28 class UndirGraphExtender : public _Base {
30 typedef UndirGraphExtender Graph;
34 typedef typename Parent::Edge UndirEdge;
35 typedef typename Parent::Node Node;
37 class Edge : public UndirEdge {
38 friend class UndirGraphExtender;
41 // FIXME: Marci use opposite logic in his graph adaptors. It would
42 // be reasonable to syncronize...
45 Edge(const UndirEdge &ue, bool _forward) :
46 UndirEdge(ue), forward(_forward) {}
51 /// Invalid edge constructor
52 Edge(Invalid i) : UndirEdge(i), forward(true) {}
54 bool operator==(const Edge &that) const {
55 return forward==that.forward && UndirEdge(*this)==UndirEdge(that);
57 bool operator!=(const Edge &that) const {
58 return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that);
60 bool operator<(const Edge &that) const {
61 return forward<that.forward ||
62 (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
67 /// \brief Edge of opposite direction.
69 /// Returns the Edge of opposite direction.
70 Edge oppositeEdge(const Edge &e) const {
71 return Edge(e,!e.forward);
77 Node _dirSource(const E &e) const {
78 return e.forward ? Parent::source(e) : Parent::target(e);
82 Node _dirTarget(const E &e) const {
83 return e.forward ? Parent::target(e) : Parent::source(e);
87 /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
91 /// Source of the given Edge.
92 Node source(const Edge &e) const {
96 /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
100 /// Target of the given Edge.
101 Node target(const Edge &e) const {
102 return _dirTarget(e);
105 Node oppositeNode(const Node &n, const UndirEdge &e) const {
106 if( n == Parent::source(e))
107 return Parent::target(e);
108 else if( n == Parent::target(e))
109 return Parent::source(e);
114 /// \brief Directed edge from an undirected edge and a source node.
116 /// Returns a (directed) Edge corresponding to the specified UndirEdge
119 Edge direct(const UndirEdge &ue, const Node &s) const {
120 return Edge(ue, s == source(ue));
123 /// \brief Directed edge from an undirected edge.
125 /// Returns a directed edge corresponding to the specified UndirEdge.
126 /// If the given bool is true the given undirected edge and the
127 /// returned edge have the same source node.
128 Edge direct(const UndirEdge &ue, bool d) const {
132 /// Returns whether the given directed edge is same orientation as the
133 /// corresponding undirected edge.
135 /// \todo reference to the corresponding point of the undirected graph
136 /// concept. "What does the direction of an undirected edge mean?"
137 bool direction(const Edge &e) const { return e.forward; }
141 void first(Edge &e) const {
147 void next(Edge &e) const {
160 template <typename E>
161 void _dirFirstOut(E &e, const Node &n) const {
162 Parent::firstIn(e,n);
163 if( UndirEdge(e) != INVALID ) {
167 Parent::firstOut(e,n);
171 template <typename E>
172 void _dirFirstIn(E &e, const Node &n) const {
173 Parent::firstOut(e,n);
174 if( UndirEdge(e) != INVALID ) {
178 Parent::firstIn(e,n);
183 template <typename E>
184 void _dirNextOut(E &e) const {
186 Node n = Parent::target(e);
188 if( UndirEdge(e) == INVALID ) {
189 Parent::firstOut(e, n);
197 template <typename E>
198 void _dirNextIn(E &e) const {
200 Node n = Parent::source(e);
202 if( UndirEdge(e) == INVALID ) {
203 Parent::firstIn(e, n);
214 void firstOut(Edge &e, const Node &n) const {
217 void firstIn(Edge &e, const Node &n) const {
221 void nextOut(Edge &e) const {
224 void nextIn(Edge &e) const {
228 // Miscellaneous stuff:
230 /// \todo these methods (id, maxEdgeId) should be moved into separate
234 // Using "using" is not a good idea, cause it could be that there is
235 // no "id" in Parent...
237 int id(const Node &n) const {
238 return Parent::id(n);
241 int id(const UndirEdge &e) const {
242 return Parent::id(e);
245 int id(const Edge &e) const {
246 return 2 * Parent::id(e) + int(e.forward);
250 int maxId(Node) const {
251 return Parent::maxId(Node());
254 int maxId(Edge) const {
255 return 2 * Parent::maxId(typename Parent::Edge()) + 1;
257 int maxId(UndirEdge) const {
258 return Parent::maxId(typename Parent::Edge());
262 int edgeNum() const {
263 return 2 * Parent::edgeNum();
265 int undirEdgeNum() const {
266 return Parent::edgeNum();
273 #endif // LEMON_UNDIR_GRAPH_EXTENDER_H