One more step towards Undir -> U conversion...
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #ifndef LEMON_LIST_GRAPH_H
20 #define LEMON_LIST_GRAPH_H
24 ///\brief ListGraph, ListUGraph classes.
26 #include <lemon/bits/erasable_graph_extender.h>
27 #include <lemon/bits/clearable_graph_extender.h>
28 #include <lemon/bits/extendable_graph_extender.h>
29 #include <lemon/bits/iterable_graph_extender.h>
30 #include <lemon/bits/alteration_notifier.h>
31 #include <lemon/bits/default_map.h>
32 #include <lemon/bits/graph_extender.h>
34 #include <lemon/error.h>
44 int first_in, first_out;
50 int prev_in, prev_out;
51 int next_in, next_out;
54 std::vector<NodeT> nodes;
60 std::vector<EdgeT> edges;
66 typedef ListGraphBase Graph;
69 friend class ListGraphBase;
73 Node(int pid) { id = pid;}
77 Node (Invalid) { id = -1; }
78 bool operator==(const Node& node) const {return id == node.id;}
79 bool operator!=(const Node& node) const {return id != node.id;}
80 bool operator<(const Node& node) const {return id < node.id;}
84 friend class ListGraphBase;
88 Edge(int pid) { id = pid;}
92 Edge (Invalid) { id = -1; }
93 bool operator==(const Edge& edge) const {return id == edge.id;}
94 bool operator!=(const Edge& edge) const {return id != edge.id;}
95 bool operator<(const Edge& edge) const {return id < edge.id;}
101 : nodes(), first_node(-1),
102 first_free_node(-1), edges(), first_free_edge(-1) {}
109 int maxNodeId() const { return nodes.size()-1; }
115 int maxEdgeId() const { return edges.size()-1; }
117 Node source(Edge e) const { return edges[e.id].source; }
118 Node target(Edge e) const { return edges[e.id].target; }
121 void first(Node& node) const {
122 node.id = first_node;
125 void next(Node& node) const {
126 node.id = nodes[node.id].next;
130 void first(Edge& e) const {
133 n!=-1 && nodes[n].first_in == -1;
135 e.id = (n == -1) ? -1 : nodes[n].first_in;
138 void next(Edge& edge) const {
139 if (edges[edge.id].next_in != -1) {
140 edge.id = edges[edge.id].next_in;
143 for(n = nodes[edges[edge.id].target].next;
144 n!=-1 && nodes[n].first_in == -1;
146 edge.id = (n == -1) ? -1 : nodes[n].first_in;
150 void firstOut(Edge &e, const Node& v) const {
151 e.id = nodes[v.id].first_out;
153 void nextOut(Edge &e) const {
154 e.id=edges[e.id].next_out;
157 void firstIn(Edge &e, const Node& v) const {
158 e.id = nodes[v.id].first_in;
160 void nextIn(Edge &e) const {
161 e.id=edges[e.id].next_in;
165 static int id(Node v) { return v.id; }
166 static int id(Edge e) { return e.id; }
168 static Node nodeFromId(int id) { return Node(id);}
169 static Edge edgeFromId(int id) { return Edge(id);}
171 /// Adds a new node to the graph.
173 /// \warning It adds the new node to the front of the list.
174 /// (i.e. the lastly added node becomes the first.)
178 if(first_free_node==-1) {
180 nodes.push_back(NodeT());
183 first_free_node = nodes[n].next;
186 nodes[n].next = first_node;
187 if(first_node != -1) nodes[first_node].prev = n;
191 nodes[n].first_in = nodes[n].first_out = -1;
196 Edge addEdge(Node u, Node v) {
199 if (first_free_edge == -1) {
201 edges.push_back(EdgeT());
204 first_free_edge = edges[n].next_in;
207 edges[n].source = u.id;
208 edges[n].target = v.id;
210 edges[n].next_out = nodes[u.id].first_out;
211 if(nodes[u.id].first_out != -1) {
212 edges[nodes[u.id].first_out].prev_out = n;
215 edges[n].next_in = nodes[v.id].first_in;
216 if(nodes[v.id].first_in != -1) {
217 edges[nodes[v.id].first_in].prev_in = n;
220 edges[n].prev_in = edges[n].prev_out = -1;
222 nodes[u.id].first_out = nodes[v.id].first_in = n;
227 void erase(const Node& node) {
230 if(nodes[n].next != -1) {
231 nodes[nodes[n].next].prev = nodes[n].prev;
234 if(nodes[n].prev != -1) {
235 nodes[nodes[n].prev].next = nodes[n].next;
237 first_node = nodes[n].next;
240 nodes[n].next = first_free_node;
245 void erase(const Edge& edge) {
248 if(edges[n].next_in!=-1) {
249 edges[edges[n].next_in].prev_in = edges[n].prev_in;
252 if(edges[n].prev_in!=-1) {
253 edges[edges[n].prev_in].next_in = edges[n].next_in;
255 nodes[edges[n].target].first_in = edges[n].next_in;
259 if(edges[n].next_out!=-1) {
260 edges[edges[n].next_out].prev_out = edges[n].prev_out;
263 if(edges[n].prev_out!=-1) {
264 edges[edges[n].prev_out].next_out = edges[n].next_out;
266 nodes[edges[n].source].first_out = edges[n].next_out;
269 edges[n].next_in = first_free_edge;
277 first_node = first_free_node = first_free_edge = -1;
281 void _changeTarget(Edge e, Node n)
283 if(edges[e.id].next_in != -1)
284 edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
285 if(edges[e.id].prev_in != -1)
286 edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
287 else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
288 if (nodes[n.id].first_in != -1) {
289 edges[nodes[n.id].first_in].prev_in = e.id;
291 edges[e.id].target = n.id;
292 edges[e.id].prev_in = -1;
293 edges[e.id].next_in = nodes[n.id].first_in;
294 nodes[n.id].first_in = e.id;
296 void _changeSource(Edge e, Node n)
298 if(edges[e.id].next_out != -1)
299 edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
300 if(edges[e.id].prev_out != -1)
301 edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
302 else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
303 if (nodes[n.id].first_out != -1) {
304 edges[nodes[n.id].first_out].prev_out = e.id;
306 edges[e.id].source = n.id;
307 edges[e.id].prev_out = -1;
308 edges[e.id].next_out = nodes[n.id].first_out;
309 nodes[n.id].first_out = e.id;
314 typedef ErasableGraphExtender<
315 ClearableGraphExtender<
316 ExtendableGraphExtender<
317 MappableGraphExtender<
318 IterableGraphExtender<
319 AlterableGraphExtender<
320 GraphExtender<ListGraphBase> > > > > > > ExtendedListGraphBase;
322 /// \addtogroup graphs
325 ///A list graph class.
327 ///This is a simple and fast erasable graph implementation.
329 ///It addition that it conforms to the
330 ///\ref concept::ErasableGraph "ErasableGraph" concept,
331 ///it also provides several additional useful extra functionalities.
332 ///\sa concept::ErasableGraph.
334 class ListGraph : public ExtendedListGraphBase
337 /// Changes the target of \c e to \c n
339 /// Changes the target of \c e to \c n
341 ///\note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
342 ///referencing the changed edge remain
343 ///valid. However <tt>InEdge</tt>'s are invalidated.
344 void changeTarget(Edge e, Node n) {
347 /// Changes the source of \c e to \c n
349 /// Changes the source of \c e to \c n
351 ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
352 ///referencing the changed edge remain
353 ///valid. However <tt>OutEdge</tt>'s are invalidated.
354 void changeSource(Edge e, Node n) {
358 /// Invert the direction of an edge.
360 ///\note The <tt>Edge</tt>'s
361 ///referencing the changed edge remain
362 ///valid. However <tt>OutEdge</tt>'s and <tt>InEdge</tt>'s are invalidated.
363 void reverseEdge(Edge e) {
365 _changeTarget(e,source(e));
369 ///Using this it possible to avoid the superfluous memory allocation.
371 ///Using this it possible to avoid the superfluous memory allocation.
372 ///\todo more docs...
373 void reserveEdge(int n) { edges.reserve(n); };
375 ///Contract two nodes.
377 ///This function contracts two nodes.
379 ///Node \p b will be removed but instead of deleting
380 ///its neighboring edges, they will be joined to \p a.
381 ///The last parameter \p r controls whether to remove loops. \c true
382 ///means that loops will be removed.
384 ///\note The <tt>Edge</tt>s
385 ///referencing a moved edge remain
386 ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
387 ///may be invalidated.
388 void contract(Node a, Node b, bool r = true)
390 for(OutEdgeIt e(*this,b);e!=INVALID;) {
393 if(r && target(e)==a) erase(e);
394 else changeSource(e,a);
397 for(InEdgeIt e(*this,b);e!=INVALID;) {
400 if(r && source(e)==a) erase(e);
401 else changeTarget(e,a);
409 ///This function splits a node. First a new node is added to the graph,
410 ///then the source of each outgoing edge of \c n is moved to this new node.
411 ///If \c connect is \c true (this is the default value), then a new edge
412 ///from \c n to the newly created node is also added.
413 ///\return The newly created node.
415 ///\note The <tt>Edge</tt>s
416 ///referencing a moved edge remain
417 ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
418 ///may be invalidated.
419 ///\warning This functionality cannot be used together with the Snapshot
421 ///\todo It could be implemented in a bit faster way.
422 Node split(Node n, bool connect = true)
425 for(OutEdgeIt e(*this,n);e!=INVALID;) {
431 if(connect) addEdge(n,b);
437 ///This function splits an edge. First a new node \c b is added to the graph,
438 ///then the original edge is re-targetes to \c b. Finally an edge
439 ///from \c b to the original target is added.
440 ///\return The newly created node.
441 ///\warning This functionality cannot be used together with the Snapshot
446 addEdge(b,target(e));
451 ///Class to make a snapshot of the graph and to restrore to it later.
453 ///Class to make a snapshot of the graph and to restrore to it later.
455 ///The newly added nodes and edges can be removed using the
456 ///restore() function.
458 ///\warning Edge and node deletions cannot be restored.
459 ///\warning Snapshots cannot be nested.
460 class Snapshot : protected AlterationNotifier<Node>::ObserverBase,
461 protected AlterationNotifier<Edge>::ObserverBase
465 class UnsupportedOperation : public LogicError {
467 virtual const char* exceptionName() const {
468 return "lemon::ListGraph::Snapshot::UnsupportedOperation";
476 std::list<Node> added_nodes;
477 std::list<Edge> added_edges;
480 virtual void add(const Node& n) {
481 added_nodes.push_back(n);
483 virtual void erase(const Node&)
485 throw UnsupportedOperation();
487 virtual void add(const Edge& n) {
488 added_edges.push_back(n);
490 virtual void erase(const Edge&)
492 throw UnsupportedOperation();
495 ///\bug What is this used for?
497 virtual void build() {}
498 ///\bug What is this used for?
500 virtual void clear() {}
502 void regist(ListGraph &_g) {
504 AlterationNotifier<Node>::ObserverBase::
505 attach(g->getNotifier(Node()));
506 AlterationNotifier<Edge>::ObserverBase::
507 attach(g->getNotifier(Edge()));
511 AlterationNotifier<Node>::ObserverBase::
513 AlterationNotifier<Edge>::ObserverBase::
519 ///Default constructur.
521 ///Default constructur.
522 ///To actually make a snapshot you must call save().
525 ///Constructor that immediately makes a snapshot.
527 ///This constructor immediately makes a snapshot of the graph.
528 ///\param _g The graph we make a snapshot of.
529 Snapshot(ListGraph &_g) {
532 ///\bug Is it necessary?
541 ///Make a snapshot of the graph.
543 ///This function can be called more than once. In case of a repeated
544 ///call, the previous snapshot gets lost.
545 ///\param _g The graph we make the snapshot of.
546 void save(ListGraph &_g)
556 ///Undo the changes until the last snapshot.
558 ///Undo the changes until last snapshot created by save().
560 ///\todo This function might be called undo().
564 while(!added_edges.empty()) {
565 old_g.erase(added_edges.front());
566 added_edges.pop_front();
568 while(!added_nodes.empty()) {
569 old_g.erase(added_nodes.front());
570 added_nodes.pop_front();
579 /**************** Undirected List Graph ****************/
581 typedef ErasableUGraphExtender<
582 ClearableUGraphExtender<
583 ExtendableUGraphExtender<
584 MappableUGraphExtender<
585 IterableUGraphExtender<
586 AlterableUGraphExtender<
587 UGraphExtender<ListGraphBase> > > > > > > ExtendedListUGraphBase;
589 /// \addtogroup graphs
592 ///An undirected list graph class.
594 ///This is a simple and fast erasable undirected graph implementation.
596 ///It conforms to the
597 ///\ref concept::UGraph "UGraph" concept.
599 ///\sa concept::UGraph.
601 ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
602 ///haven't been implemented yet.
604 class ListUGraph : public ExtendedListUGraphBase {
606 typedef ExtendedListUGraphBase Parent;
607 /// \brief Changes the target of \c e to \c n
609 /// Changes the target of \c e to \c n
611 /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
612 /// referencing the changed edge remain
613 /// valid. However <tt>InEdge</tt>'s are invalidated.
614 void changeTarget(UEdge e, Node n) {
617 /// Changes the source of \c e to \c n
619 /// Changes the source of \c e to \c n
621 ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
622 ///referencing the changed edge remain
623 ///valid. However <tt>OutEdge</tt>'s are invalidated.
624 void changeSource(UEdge e, Node n) {
627 /// \brief Contract two nodes.
629 /// This function contracts two nodes.
631 /// Node \p b will be removed but instead of deleting
632 /// its neighboring edges, they will be joined to \p a.
633 /// The last parameter \p r controls whether to remove loops. \c true
634 /// means that loops will be removed.
636 /// \note The <tt>Edge</tt>s
637 /// referencing a moved edge remain
639 void contract(Node a, Node b, bool r = true) {
640 for(IncEdgeIt e(*this, b); e!=INVALID;) {
641 IncEdgeIt f = e; ++f;
642 if (r && runningNode(e) == a) {
644 } else if (source(e) == b) {