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);
75 /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
79 /// Source of the given Edge.
80 Node source(const Edge &e) const {
81 return e.forward ? Parent::source(e) : Parent::target(e);
84 /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
88 /// Target of the given Edge.
89 Node target(const Edge &e) const {
90 return e.forward ? Parent::target(e) : Parent::source(e);
93 Node oppositeNode(const Node &n, const UndirEdge &e) const {
94 if( n == Parent::source(e))
95 return Parent::target(e);
96 else if( n == Parent::target(e))
97 return Parent::source(e);
102 /// \brief Directed edge from an undirected edge and a source node.
104 /// Returns a (directed) Edge corresponding to the specified UndirEdge
107 Edge direct(const UndirEdge &ue, const Node &s) const {
108 return Edge(ue, s == source(ue));
111 /// \brief Directed edge from an undirected edge.
113 /// Returns a directed edge corresponding to the specified UndirEdge.
114 /// If the given bool is true the given undirected edge and the
115 /// returned edge have the same source node.
116 Edge direct(const UndirEdge &ue, bool d) const {
120 /// Returns whether the given directed edge is same orientation as the
121 /// corresponding undirected edge.
123 /// \todo reference to the corresponding point of the undirected graph
124 /// concept. "What does the direction of an undirected edge mean?"
125 bool direction(const Edge &e) const { return e.forward; }
129 void first(Edge &e) const {
135 void next(Edge &e) const {
147 void firstOut(Edge &e, const Node &n) const {
148 Parent::firstIn(e,n);
149 if( UndirEdge(e) != INVALID ) {
153 Parent::firstOut(e,n);
157 void nextOut(Edge &e) const {
159 Node n = Parent::target(e);
161 if( UndirEdge(e) == INVALID ) {
162 Parent::firstOut(e, n);
171 void firstIn(Edge &e, const Node &n) const {
172 Parent::firstOut(e,n);
173 if( UndirEdge(e) != INVALID ) {
177 Parent::firstIn(e,n);
181 void nextIn(Edge &e) const {
183 Node n = Parent::source(e);
185 if( UndirEdge(e) == INVALID ) {
186 Parent::firstIn(e, n);
195 void firstInc(UndirEdge &e, const Node &n) const {
196 Parent::firstOut(e, n);
197 if (e != INVALID) return;
198 Parent::firstIn(e, n);
200 void nextInc(UndirEdge &e, const Node &n) const {
201 if (Parent::source(e) == n) {
203 if (e != INVALID) return;
204 Parent::firstIn(e, n);
210 void firstInc(UndirEdge &e, bool &d, const Node &n) const {
212 Parent::firstOut(e, n);
213 if (e != INVALID) return;
215 Parent::firstIn(e, n);
217 void nextInc(UndirEdge &e, bool &d) const {
219 Node s = Parent::source(e);
221 if (e != INVALID) return;
223 Parent::firstIn(e, s);
229 // Miscellaneous stuff:
231 /// \todo these methods (id, maxEdgeId) should be moved into separate
235 // Using "using" is not a good idea, cause it could be that there is
236 // no "id" in Parent...
238 int id(const Node &n) const {
239 return Parent::id(n);
242 int id(const UndirEdge &e) const {
243 return Parent::id(e);
246 int id(const Edge &e) const {
247 return 2 * Parent::id(e) + int(e.forward);
251 int maxId(Node) const {
252 return Parent::maxId(Node());
255 int maxId(Edge) const {
256 return 2 * Parent::maxId(typename Parent::Edge()) + 1;
258 int maxId(UndirEdge) const {
259 return Parent::maxId(typename Parent::Edge());
263 int edgeNum() const {
264 return 2 * Parent::edgeNum();
267 int undirEdgeNum() const {
268 return Parent::edgeNum();
271 Edge findEdge(Node source, Node target, Edge prev) const {
272 if (prev == INVALID) {
273 UndirEdge edge = Parent::findEdge(source, target);
274 if (edge != INVALID) return direct(edge, true);
275 edge = Parent::findEdge(target, source);
276 if (edge != INVALID) return direct(edge, false);
277 } else if (direction(prev)) {
278 UndirEdge edge = Parent::findEdge(source, target, prev);
279 if (edge != INVALID) return direct(edge, true);
280 edge = Parent::findEdge(target, source);
281 if (edge != INVALID) return direct(edge, false);
283 UndirEdge edge = Parent::findEdge(target, source, prev);
284 if (edge != INVALID) return direct(edge, false);
289 UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const {
290 if (prev == INVALID) {
291 UndirEdge edge = Parent::findEdge(source, target);
292 if (edge != INVALID) return edge;
293 edge = Parent::findEdge(target, source);
294 if (edge != INVALID) return edge;
295 } else if (Parent::source(prev) == source) {
296 UndirEdge edge = Parent::findEdge(source, target, prev);
297 if (edge != INVALID) return edge;
298 edge = Parent::findEdge(target, source);
299 if (edge != INVALID) return edge;
301 UndirEdge edge = Parent::findEdge(target, source, prev);
302 if (edge != INVALID) return edge;
311 #endif // LEMON_UNDIR_GRAPH_EXTENDER_H