|
1 /* -*- C++ -*- |
|
2 * lemon/edge_set.h - Part of LEMON, a generic C++ optimization library |
|
3 * |
|
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
5 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
6 * |
|
7 * Permission to use, modify and distribute this software is granted |
|
8 * provided that this copyright notice appears in all copies. For |
|
9 * precise terms see the accompanying LICENSE file. |
|
10 * |
|
11 * This software is provided "AS IS" with no warranty of any kind, |
|
12 * express or implied, and with no claim as to its suitability for any |
|
13 * purpose. |
|
14 * |
|
15 */ |
|
16 |
|
17 #ifndef LEMON_EDGE_SET_H |
|
18 #define LEMON_EDGE_SET_H |
|
19 |
|
20 /// \ingroup graphs |
|
21 /// \file |
|
22 /// \brief EdgeSet classes. |
|
23 /// |
|
24 /// Graphs which use another graph's node-set as own. |
|
25 |
|
26 namespace lemon { |
|
27 |
|
28 template <typename _Graph> |
|
29 class ListEdgeSetBase { |
|
30 public: |
|
31 |
|
32 typedef _Graph Graph; |
|
33 typedef typename Graph::Node Node; |
|
34 typedef typename Graph::NodeIt NodeIt; |
|
35 |
|
36 protected: |
|
37 |
|
38 struct NodeT { |
|
39 int first_out, first_in; |
|
40 NodeT() : first_out(-1), first_in(-1) {} |
|
41 }; |
|
42 |
|
43 typedef typename Graph::template NodeMap<NodeT> NodesImplBase; |
|
44 |
|
45 NodesImplBase* nodes; |
|
46 |
|
47 struct EdgeT { |
|
48 Node source, target; |
|
49 int next_out, next_in; |
|
50 int prev_out, prev_in; |
|
51 EdgeT() : prev_out(-1), prev_in(-1) {} |
|
52 }; |
|
53 |
|
54 std::vector<EdgeT> edges; |
|
55 |
|
56 int first_edge; |
|
57 int first_free_edge; |
|
58 |
|
59 const Graph* graph; |
|
60 |
|
61 void initalize(const Graph& _graph, NodesImplBase& _nodes) { |
|
62 graph = &_graph; |
|
63 nodes = &_nodes; |
|
64 } |
|
65 |
|
66 public: |
|
67 |
|
68 class Edge { |
|
69 friend class ListEdgeSetBase<Graph>; |
|
70 protected: |
|
71 Edge(int _id) : id(_id) {} |
|
72 int id; |
|
73 public: |
|
74 Edge() {} |
|
75 Edge(Invalid) : id(-1) {} |
|
76 bool operator==(const Edge& edge) const { return id == edge.id; } |
|
77 bool operator!=(const Edge& edge) const { return id != edge.id; } |
|
78 bool operator<(const Edge& edge) const { return id < edge.id; } |
|
79 }; |
|
80 |
|
81 ListEdgeSetBase() : first_edge(-1), first_free_edge(-1) {} |
|
82 |
|
83 Edge addEdge(const Node& source, const Node& target) { |
|
84 int n; |
|
85 if (first_free_edge == -1) { |
|
86 n = edges.size(); |
|
87 edges.push_back(EdgeT()); |
|
88 } else { |
|
89 n = first_free_edge; |
|
90 first_free_edge = edges[first_free_edge].next_in; |
|
91 } |
|
92 edges[n].next_in = (*nodes)[target].first_in; |
|
93 (*nodes)[target].first_in = n; |
|
94 edges[n].next_out = (*nodes)[source].first_out; |
|
95 (*nodes)[source].first_out = n; |
|
96 edges[n].source = source; |
|
97 edges[n].target = target; |
|
98 return Edge(n); |
|
99 } |
|
100 |
|
101 void erase(const Edge& edge) { |
|
102 int n = edge.id; |
|
103 if (edges[n].prev_in != -1) { |
|
104 edges[edges[n].prev_in].next_in = edges[n].next_in; |
|
105 } else { |
|
106 (*nodes)[edges[n].target].first_in = edges[n].next_in; |
|
107 } |
|
108 if (edges[n].next_in != -1) { |
|
109 edges[edges[n].next_in].prev_in = edges[n].prev_in; |
|
110 } |
|
111 |
|
112 if (edges[n].prev_out != -1) { |
|
113 edges[edges[n].prev_out].next_out = edges[n].next_out; |
|
114 } else { |
|
115 (*nodes)[edges[n].source].first_out = edges[n].next_out; |
|
116 } |
|
117 if (edges[n].next_out != -1) { |
|
118 edges[edges[n].next_out].prev_out = edges[n].prev_out; |
|
119 } |
|
120 |
|
121 } |
|
122 |
|
123 void clear() { |
|
124 edges.clear(); |
|
125 first_edge = -1; |
|
126 first_free_edge = -1; |
|
127 } |
|
128 |
|
129 void first(Node& node) const { |
|
130 graph->first(node); |
|
131 } |
|
132 |
|
133 void next(Node& node) const { |
|
134 graph->next(node); |
|
135 } |
|
136 |
|
137 void first(Edge& edge) const { |
|
138 Node node; |
|
139 for (first(node); node != INVALID && (*nodes)[node].first_in == -1; |
|
140 next(node)); |
|
141 edge.id = (node == INVALID) ? -1 : (*nodes)[node].first_in; |
|
142 } |
|
143 |
|
144 void next(Edge& edge) const { |
|
145 if (edges[edge.id].next_in != -1) { |
|
146 edge.id = edges[edge.id].next_in; |
|
147 } else { |
|
148 Node node = edges[edge.id].target; |
|
149 for (next(node); node != INVALID && (*nodes)[node].first_in == -1; |
|
150 next(node)); |
|
151 edge.id = (node == INVALID) ? -1 : (*nodes)[node].first_in; |
|
152 } |
|
153 } |
|
154 |
|
155 void firstOut(Edge& edge, const Node& node) const { |
|
156 edge.id = (*nodes)[node].first_out; |
|
157 } |
|
158 |
|
159 void nextOut(Edge& edge) const { |
|
160 edge.id = edges[edge.id].next_out; |
|
161 } |
|
162 |
|
163 void firstIn(Edge& edge, const Node& node) const { |
|
164 edge.id = (*nodes)[node].first_in; |
|
165 } |
|
166 |
|
167 void nextIn(Edge& edge) const { |
|
168 edge.id = edges[edge.id].next_in; |
|
169 } |
|
170 |
|
171 int id(const Node& node) const { return graph->id(node); } |
|
172 int id(const Edge& edge) const { return edge.id; } |
|
173 |
|
174 Node nodeFromId(int id) const { return graph->fromId(id, Node()); } |
|
175 Edge edgeFromId(int id) const { return Edge(id); } |
|
176 |
|
177 int maxNodeId() const { return graph->maxId(Node()); }; |
|
178 int maxEdgeId() const { return edges.size() - 1; } |
|
179 |
|
180 Node source(const Edge& edge) const { return edges[edge.id].source;} |
|
181 Node target(const Edge& edge) const { return edges[edge.id].target;} |
|
182 |
|
183 template <typename _Value> |
|
184 class NodeMap : public Graph::template NodeMap<_Value> { |
|
185 public: |
|
186 typedef typename _Graph::template NodeMap<_Value> Parent; |
|
187 explicit NodeMap(const ListEdgeSetBase<Graph>& edgeset) |
|
188 : Parent(*edgeset.graph) { } |
|
189 NodeMap(const ListEdgeSetBase<Graph>& edgeset, const _Value& value) |
|
190 : Parent(*edgeset.graph, value) { } |
|
191 }; |
|
192 |
|
193 }; |
|
194 |
|
195 /// \ingroup graphs |
|
196 /// |
|
197 /// \brief Graph using a node set of another graph and an |
|
198 /// own edge set. |
|
199 /// |
|
200 /// This structure can be used to establish another graph over a node set |
|
201 /// of an existing one. The node iterator will go through the nodes of the |
|
202 /// original graph. |
|
203 /// |
|
204 /// \param _Graph The type of the graph which shares its node set with |
|
205 /// this class. Its interface must conform to the \ref concept::StaticGraph |
|
206 /// "StaticGraph" concept. |
|
207 /// |
|
208 /// In the edge extension and removing it conforms to the |
|
209 /// \ref concept::ExtendableGraph "ExtendableGraph" concept. |
|
210 template <typename _Graph> |
|
211 class ListEdgeSet : |
|
212 public ErasableEdgeSetExtender< |
|
213 ClearableEdgeSetExtender< |
|
214 ExtendableEdgeSetExtender< |
|
215 MappableEdgeSetExtender< |
|
216 IterableGraphExtender< |
|
217 AlterableEdgeSetExtender< |
|
218 GraphExtender< |
|
219 ListEdgeSetBase<_Graph> > > > > > > > { |
|
220 |
|
221 public: |
|
222 |
|
223 typedef ErasableEdgeSetExtender< |
|
224 ClearableEdgeSetExtender< |
|
225 ExtendableEdgeSetExtender< |
|
226 MappableEdgeSetExtender< |
|
227 IterableGraphExtender< |
|
228 AlterableEdgeSetExtender< |
|
229 GraphExtender< |
|
230 ListEdgeSetBase<_Graph> > > > > > > > Parent; |
|
231 |
|
232 typedef typename Parent::Node Node; |
|
233 typedef typename Parent::Edge Edge; |
|
234 |
|
235 typedef _Graph Graph; |
|
236 |
|
237 |
|
238 typedef typename Parent::NodesImplBase NodesImplBase; |
|
239 |
|
240 void eraseNode(const Node& node) { |
|
241 Edge edge; |
|
242 Parent::firstOut(edge, node); |
|
243 while (edge != INVALID ) { |
|
244 erase(edge); |
|
245 Parent::firstOut(edge, node); |
|
246 } |
|
247 |
|
248 Parent::firstIn(edge, node); |
|
249 while (edge != INVALID ) { |
|
250 erase(edge); |
|
251 Parent::firstIn(edge, node); |
|
252 } |
|
253 } |
|
254 |
|
255 void clearNodes() { |
|
256 Parent::clear(); |
|
257 } |
|
258 |
|
259 class NodesImpl : public NodesImplBase { |
|
260 public: |
|
261 typedef NodesImplBase Parent; |
|
262 |
|
263 NodesImpl(const Graph& graph, ListEdgeSet& edgeset) |
|
264 : Parent(graph), _edgeset(edgeset) {} |
|
265 |
|
266 protected: |
|
267 |
|
268 virtual void erase(const Node& node) { |
|
269 _edgeset.eraseNode(node); |
|
270 Parent::erase(node); |
|
271 } |
|
272 virtual void clear() { |
|
273 _edgeset.clearNodes(); |
|
274 Parent::clear(); |
|
275 } |
|
276 |
|
277 private: |
|
278 ListEdgeSet& _edgeset; |
|
279 }; |
|
280 |
|
281 NodesImpl nodes; |
|
282 |
|
283 public: |
|
284 |
|
285 /// \brief Constructor of the adaptor. |
|
286 /// |
|
287 /// Constructor of the adaptor. |
|
288 ListEdgeSet(const Graph& graph) : nodes(graph, *this) { |
|
289 Parent::initalize(graph, nodes); |
|
290 } |
|
291 |
|
292 }; |
|
293 |
|
294 /// \ingroup graphs |
|
295 /// |
|
296 /// \brief Graph using a node set of another graph and an |
|
297 /// own undir edge set. |
|
298 /// |
|
299 /// This structure can be used to establish another graph over a node set |
|
300 /// of an existing one. The node iterator will go through the nodes of the |
|
301 /// original graph. |
|
302 /// |
|
303 /// \param _Graph The type of the graph which shares its node set with |
|
304 /// this class. Its interface must conform to the \ref concept::StaticGraph |
|
305 /// "StaticGraph" concept. |
|
306 /// |
|
307 /// In the edge extension and removing it conforms to the |
|
308 /// \ref concept::ExtendableGraph "ExtendableGraph" concept. |
|
309 template <typename _Graph> |
|
310 class ListUndirEdgeSet : |
|
311 public ErasableUndirEdgeSetExtender< |
|
312 ClearableUndirEdgeSetExtender< |
|
313 ExtendableUndirEdgeSetExtender< |
|
314 MappableUndirEdgeSetExtender< |
|
315 IterableUndirGraphExtender< |
|
316 AlterableUndirEdgeSetExtender< |
|
317 UndirGraphExtender< |
|
318 ListEdgeSetBase<_Graph> > > > > > > > { |
|
319 |
|
320 public: |
|
321 |
|
322 typedef ErasableUndirEdgeSetExtender< |
|
323 ClearableUndirEdgeSetExtender< |
|
324 ExtendableUndirEdgeSetExtender< |
|
325 MappableUndirEdgeSetExtender< |
|
326 IterableUndirGraphExtender< |
|
327 AlterableUndirEdgeSetExtender< |
|
328 UndirGraphExtender< |
|
329 ListEdgeSetBase<_Graph> > > > > > > > Parent; |
|
330 |
|
331 typedef typename Parent::Node Node; |
|
332 typedef typename Parent::Edge Edge; |
|
333 |
|
334 typedef _Graph Graph; |
|
335 |
|
336 |
|
337 typedef typename Parent::NodesImplBase NodesImplBase; |
|
338 |
|
339 void eraseNode(const Node& node) { |
|
340 Edge edge; |
|
341 Parent::firstOut(edge, node); |
|
342 while (edge != INVALID ) { |
|
343 erase(edge); |
|
344 Parent::firstOut(edge, node); |
|
345 } |
|
346 |
|
347 } |
|
348 |
|
349 void clearNodes() { |
|
350 Parent::clear(); |
|
351 } |
|
352 |
|
353 class NodesImpl : public NodesImplBase { |
|
354 public: |
|
355 typedef NodesImplBase Parent; |
|
356 |
|
357 NodesImpl(const Graph& graph, ListUndirEdgeSet& edgeset) |
|
358 : Parent(graph), _edgeset(edgeset) {} |
|
359 |
|
360 protected: |
|
361 |
|
362 virtual void erase(const Node& node) { |
|
363 _edgeset.eraseNode(node); |
|
364 Parent::erase(node); |
|
365 } |
|
366 virtual void clear() { |
|
367 _edgeset.clearNodes(); |
|
368 Parent::clear(); |
|
369 } |
|
370 |
|
371 private: |
|
372 ListUndirEdgeSet& _edgeset; |
|
373 }; |
|
374 |
|
375 NodesImpl nodes; |
|
376 |
|
377 public: |
|
378 |
|
379 /// \brief Constructor of the adaptor. |
|
380 /// |
|
381 /// Constructor of the adaptor. |
|
382 ListUndirEdgeSet(const Graph& graph) : nodes(graph, *this) { |
|
383 Parent::initalize(graph, nodes); |
|
384 } |
|
385 |
|
386 }; |
|
387 |
|
388 } |
|
389 |
|
390 #endif |