alpar@209: /* -*- mode: C++; indent-tabs-mode: nil; -*- alpar@39: * alpar@209: * This file is a part of LEMON, a generic C++ optimization library. alpar@39: * alpar@1092: * Copyright (C) 2003-2013 alpar@39: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@39: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@39: * alpar@39: * Permission to use, modify and distribute this software is granted alpar@39: * provided that this copyright notice appears in all copies. For alpar@39: * precise terms see the accompanying LICENSE file. alpar@39: * alpar@39: * This software is provided "AS IS" with no warranty of any kind, alpar@39: * express or implied, and with no claim as to its suitability for any alpar@39: * purpose. alpar@39: * alpar@39: */ alpar@39: deba@57: #ifndef LEMON_LIST_GRAPH_H deba@57: #define LEMON_LIST_GRAPH_H deba@57: deba@57: ///\ingroup graphs deba@57: ///\file kpeter@735: ///\brief ListDigraph and ListGraph classes. deba@57: deba@220: #include deba@220: #include deba@57: #include deba@57: deba@57: #include deba@57: #include deba@57: deba@57: namespace lemon { deba@57: kpeter@738: class ListDigraph; kpeter@738: deba@57: class ListDigraphBase { deba@57: deba@57: protected: deba@57: struct NodeT { deba@57: int first_in, first_out; deba@57: int prev, next; deba@57: }; alpar@209: deba@57: struct ArcT { deba@57: int target, source; deba@57: int prev_in, prev_out; deba@57: int next_in, next_out; deba@57: }; deba@57: ggab90@1130: std::vector _nodes; deba@57: deba@57: int first_node; deba@57: deba@57: int first_free_node; deba@57: ggab90@1130: std::vector _arcs; deba@57: deba@57: int first_free_arc; alpar@209: deba@57: public: alpar@209: deba@57: typedef ListDigraphBase Digraph; alpar@209: deba@57: class Node { deba@57: friend class ListDigraphBase; kpeter@738: friend class ListDigraph; deba@57: protected: deba@57: deba@57: int id; deba@57: explicit Node(int pid) { id = pid;} deba@57: deba@57: public: deba@57: Node() {} deba@57: Node (Invalid) { id = -1; } deba@57: bool operator==(const Node& node) const {return id == node.id;} deba@57: bool operator!=(const Node& node) const {return id != node.id;} deba@57: bool operator<(const Node& node) const {return id < node.id;} deba@57: }; deba@57: deba@57: class Arc { deba@57: friend class ListDigraphBase; kpeter@738: friend class ListDigraph; deba@57: protected: deba@57: deba@57: int id; deba@57: explicit Arc(int pid) { id = pid;} deba@57: deba@57: public: deba@57: Arc() {} deba@57: Arc (Invalid) { id = -1; } deba@57: bool operator==(const Arc& arc) const {return id == arc.id;} deba@57: bool operator!=(const Arc& arc) const {return id != arc.id;} deba@57: bool operator<(const Arc& arc) const {return id < arc.id;} deba@57: }; deba@57: deba@57: deba@57: deba@57: ListDigraphBase() ggab90@1130: : _nodes(), first_node(-1), ggab90@1130: first_free_node(-1), _arcs(), first_free_arc(-1) {} ggab90@1130: ggab90@1130: ggab90@1130: int maxNodeId() const { return _nodes.size()-1; } ggab90@1130: int maxArcId() const { return _arcs.size()-1; } ggab90@1130: ggab90@1130: Node source(Arc e) const { return Node(_arcs[e.id].source); } ggab90@1130: Node target(Arc e) const { return Node(_arcs[e.id].target); } deba@57: deba@57: alpar@209: void first(Node& node) const { deba@57: node.id = first_node; deba@57: } deba@57: deba@57: void next(Node& node) const { ggab90@1130: node.id = _nodes[node.id].next; deba@57: } deba@57: deba@57: alpar@209: void first(Arc& arc) const { deba@57: int n; alpar@209: for(n = first_node; ggab90@1130: n != -1 && _nodes[n].first_out == -1; ggab90@1130: n = _nodes[n].next) {} ggab90@1130: arc.id = (n == -1) ? -1 : _nodes[n].first_out; deba@57: } deba@57: deba@57: void next(Arc& arc) const { ggab90@1130: if (_arcs[arc.id].next_out != -1) { ggab90@1130: arc.id = _arcs[arc.id].next_out; deba@57: } else { alpar@209: int n; ggab90@1130: for(n = _nodes[_arcs[arc.id].source].next; ggab90@1130: n != -1 && _nodes[n].first_out == -1; ggab90@1130: n = _nodes[n].next) {} ggab90@1130: arc.id = (n == -1) ? -1 : _nodes[n].first_out; alpar@209: } deba@57: } deba@57: deba@57: void firstOut(Arc &e, const Node& v) const { ggab90@1130: e.id = _nodes[v.id].first_out; deba@57: } deba@57: void nextOut(Arc &e) const { ggab90@1130: e.id=_arcs[e.id].next_out; deba@57: } deba@57: deba@57: void firstIn(Arc &e, const Node& v) const { ggab90@1130: e.id = _nodes[v.id].first_in; deba@57: } deba@57: void nextIn(Arc &e) const { ggab90@1130: e.id=_arcs[e.id].next_in; deba@57: } deba@57: alpar@209: deba@57: static int id(Node v) { return v.id; } deba@57: static int id(Arc e) { return e.id; } deba@57: deba@57: static Node nodeFromId(int id) { return Node(id);} deba@57: static Arc arcFromId(int id) { return Arc(id);} deba@57: alpar@209: bool valid(Node n) const { ggab90@1130: return n.id >= 0 && n.id < static_cast(_nodes.size()) && ggab90@1130: _nodes[n.id].prev != -2; deba@149: } deba@149: alpar@209: bool valid(Arc a) const { ggab90@1130: return a.id >= 0 && a.id < static_cast(_arcs.size()) && ggab90@1130: _arcs[a.id].prev_in != -2; deba@149: } deba@149: alpar@209: Node addNode() { deba@57: int n; alpar@209: deba@57: if(first_free_node==-1) { ggab90@1130: n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); deba@57: } else { alpar@209: n = first_free_node; ggab90@1130: first_free_node = _nodes[n].next; deba@57: } alpar@209: ggab90@1130: _nodes[n].next = first_node; ggab90@1130: if(first_node != -1) _nodes[first_node].prev = n; deba@57: first_node = n; ggab90@1130: _nodes[n].prev = -1; ggab90@1130: ggab90@1130: _nodes[n].first_in = _nodes[n].first_out = -1; alpar@209: deba@57: return Node(n); deba@57: } alpar@209: deba@57: Arc addArc(Node u, Node v) { alpar@209: int n; deba@57: deba@57: if (first_free_arc == -1) { ggab90@1130: n = _arcs.size(); ggab90@1130: _arcs.push_back(ArcT()); deba@57: } else { alpar@209: n = first_free_arc; ggab90@1130: first_free_arc = _arcs[n].next_in; deba@57: } alpar@209: ggab90@1130: _arcs[n].source = u.id; ggab90@1130: _arcs[n].target = v.id; ggab90@1130: ggab90@1130: _arcs[n].next_out = _nodes[u.id].first_out; ggab90@1130: if(_nodes[u.id].first_out != -1) { ggab90@1130: _arcs[_nodes[u.id].first_out].prev_out = n; deba@57: } alpar@209: ggab90@1130: _arcs[n].next_in = _nodes[v.id].first_in; ggab90@1130: if(_nodes[v.id].first_in != -1) { ggab90@1130: _arcs[_nodes[v.id].first_in].prev_in = n; deba@57: } alpar@209: ggab90@1130: _arcs[n].prev_in = _arcs[n].prev_out = -1; ggab90@1130: ggab90@1130: _nodes[u.id].first_out = _nodes[v.id].first_in = n; deba@57: deba@57: return Arc(n); deba@57: } alpar@209: deba@57: void erase(const Node& node) { deba@57: int n = node.id; alpar@209: ggab90@1130: if(_nodes[n].next != -1) { ggab90@1130: _nodes[_nodes[n].next].prev = _nodes[n].prev; deba@57: } alpar@209: ggab90@1130: if(_nodes[n].prev != -1) { ggab90@1130: _nodes[_nodes[n].prev].next = _nodes[n].next; deba@57: } else { ggab90@1130: first_node = _nodes[n].next; deba@57: } alpar@209: ggab90@1130: _nodes[n].next = first_free_node; deba@57: first_free_node = n; ggab90@1130: _nodes[n].prev = -2; deba@57: deba@57: } alpar@209: deba@57: void erase(const Arc& arc) { deba@57: int n = arc.id; alpar@209: ggab90@1130: if(_arcs[n].next_in!=-1) { ggab90@1130: _arcs[_arcs[n].next_in].prev_in = _arcs[n].prev_in; deba@57: } deba@57: ggab90@1130: if(_arcs[n].prev_in!=-1) { ggab90@1130: _arcs[_arcs[n].prev_in].next_in = _arcs[n].next_in; deba@57: } else { ggab90@1130: _nodes[_arcs[n].target].first_in = _arcs[n].next_in; deba@57: } deba@57: alpar@209: ggab90@1130: if(_arcs[n].next_out!=-1) { ggab90@1130: _arcs[_arcs[n].next_out].prev_out = _arcs[n].prev_out; alpar@209: } deba@57: ggab90@1130: if(_arcs[n].prev_out!=-1) { ggab90@1130: _arcs[_arcs[n].prev_out].next_out = _arcs[n].next_out; deba@57: } else { ggab90@1130: _nodes[_arcs[n].source].first_out = _arcs[n].next_out; deba@57: } alpar@209: ggab90@1130: _arcs[n].next_in = first_free_arc; deba@149: first_free_arc = n; ggab90@1130: _arcs[n].prev_in = -2; deba@57: } deba@57: deba@57: void clear() { ggab90@1130: _arcs.clear(); ggab90@1130: _nodes.clear(); deba@57: first_node = first_free_node = first_free_arc = -1; deba@57: } deba@57: deba@57: protected: alpar@209: void changeTarget(Arc e, Node n) deba@57: { ggab90@1130: if(_arcs[e.id].next_in != -1) ggab90@1130: _arcs[_arcs[e.id].next_in].prev_in = _arcs[e.id].prev_in; ggab90@1130: if(_arcs[e.id].prev_in != -1) ggab90@1130: _arcs[_arcs[e.id].prev_in].next_in = _arcs[e.id].next_in; ggab90@1130: else _nodes[_arcs[e.id].target].first_in = _arcs[e.id].next_in; ggab90@1130: if (_nodes[n.id].first_in != -1) { ggab90@1130: _arcs[_nodes[n.id].first_in].prev_in = e.id; deba@57: } ggab90@1130: _arcs[e.id].target = n.id; ggab90@1130: _arcs[e.id].prev_in = -1; ggab90@1130: _arcs[e.id].next_in = _nodes[n.id].first_in; ggab90@1130: _nodes[n.id].first_in = e.id; deba@57: } alpar@209: void changeSource(Arc e, Node n) deba@57: { ggab90@1130: if(_arcs[e.id].next_out != -1) ggab90@1130: _arcs[_arcs[e.id].next_out].prev_out = _arcs[e.id].prev_out; ggab90@1130: if(_arcs[e.id].prev_out != -1) ggab90@1130: _arcs[_arcs[e.id].prev_out].next_out = _arcs[e.id].next_out; ggab90@1130: else _nodes[_arcs[e.id].source].first_out = _arcs[e.id].next_out; ggab90@1130: if (_nodes[n.id].first_out != -1) { ggab90@1130: _arcs[_nodes[n.id].first_out].prev_out = e.id; deba@57: } ggab90@1130: _arcs[e.id].source = n.id; ggab90@1130: _arcs[e.id].prev_out = -1; ggab90@1130: _arcs[e.id].next_out = _nodes[n.id].first_out; ggab90@1130: _nodes[n.id].first_out = e.id; deba@57: } deba@57: deba@57: }; deba@57: deba@57: typedef DigraphExtender ExtendedListDigraphBase; deba@57: kpeter@73: /// \addtogroup graphs deba@57: /// @{ deba@57: alpar@209: ///A general directed graph structure. deba@57: kpeter@735: ///\ref ListDigraph is a versatile and fast directed graph kpeter@735: ///implementation based on linked lists that are stored in alpar@209: ///\c std::vector structures. deba@57: /// kpeter@735: ///This type fully conforms to the \ref concepts::Digraph "Digraph concept" kpeter@735: ///and it also provides several useful additional functionalities. kpeter@735: ///Most of its member functions and nested classes are documented kpeter@73: ///only in the concept class. deba@57: /// kpeter@787: ///This class provides only linear time counting for nodes and arcs. kpeter@787: /// kpeter@73: ///\sa concepts::Digraph kpeter@735: ///\sa ListGraph deba@57: class ListDigraph : public ExtendedListDigraphBase { kpeter@617: typedef ExtendedListDigraphBase Parent; kpeter@617: deba@57: private: kpeter@735: /// Digraphs are \e not copy constructible. Use DigraphCopy instead. deba@57: ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {}; kpeter@735: /// \brief Assignment of a digraph to another one is \e not allowed. kpeter@735: /// Use DigraphCopy instead. deba@57: void operator=(const ListDigraph &) {} deba@57: public: deba@57: deba@57: /// Constructor alpar@209: deba@57: /// Constructor. deba@57: /// deba@57: ListDigraph() {} deba@57: deba@57: ///Add a new node to the digraph. alpar@209: kpeter@735: ///This function adds a new node to the digraph. kpeter@559: ///\return The new node. deba@57: Node addNode() { return Parent::addNode(); } deba@57: deba@57: ///Add a new arc to the digraph. alpar@209: kpeter@735: ///This function adds a new arc to the digraph with source node \c s deba@57: ///and target node \c t. kpeter@559: ///\return The new arc. kpeter@735: Arc addArc(Node s, Node t) { alpar@209: return Parent::addArc(s, t); deba@57: } deba@57: deba@234: ///\brief Erase a node from the digraph. deba@234: /// kpeter@787: ///This function erases the given node along with its outgoing and kpeter@787: ///incoming arcs from the digraph. kpeter@787: /// kpeter@787: ///\note All iterators referencing the removed node or the connected kpeter@787: ///arcs are invalidated, of course. kpeter@735: void erase(Node n) { Parent::erase(n); } deba@234: deba@234: ///\brief Erase an arc from the digraph. deba@234: /// kpeter@735: ///This function erases the given arc from the digraph. kpeter@787: /// kpeter@787: ///\note All iterators referencing the removed arc are invalidated, kpeter@787: ///of course. kpeter@735: void erase(Arc a) { Parent::erase(a); } deba@234: deba@149: /// Node validity check deba@149: kpeter@735: /// This function gives back \c true if the given node is valid, kpeter@735: /// i.e. it is a real node of the digraph. deba@149: /// kpeter@735: /// \warning A removed node could become valid again if new nodes are kpeter@735: /// added to the digraph. deba@149: bool valid(Node n) const { return Parent::valid(n); } deba@149: deba@149: /// Arc validity check deba@149: kpeter@735: /// This function gives back \c true if the given arc is valid, kpeter@735: /// i.e. it is a real arc of the digraph. deba@149: /// kpeter@735: /// \warning A removed arc could become valid again if new arcs are kpeter@735: /// added to the digraph. deba@149: bool valid(Arc a) const { return Parent::valid(a); } deba@149: kpeter@735: /// Change the target node of an arc deba@57: kpeter@735: /// This function changes the target node of the given arc \c a to \c n. deba@57: /// kpeter@735: ///\note \c ArcIt and \c OutArcIt iterators referencing the changed kpeter@786: ///arc remain valid, but \c InArcIt iterators are invalidated. kpeter@73: /// deba@57: ///\warning This functionality cannot be used together with the Snapshot deba@57: ///feature. deba@235: void changeTarget(Arc a, Node n) { deba@235: Parent::changeTarget(a,n); deba@57: } kpeter@735: /// Change the source node of an arc deba@57: kpeter@735: /// This function changes the source node of the given arc \c a to \c n. deba@57: /// kpeter@735: ///\note \c InArcIt iterators referencing the changed arc remain kpeter@786: ///valid, but \c ArcIt and \c OutArcIt iterators are invalidated. kpeter@73: /// deba@57: ///\warning This functionality cannot be used together with the Snapshot deba@57: ///feature. deba@235: void changeSource(Arc a, Node n) { deba@235: Parent::changeSource(a,n); deba@57: } deba@57: kpeter@735: /// Reverse the direction of an arc. deba@57: kpeter@735: /// This function reverses the direction of the given arc. kpeter@735: ///\note \c ArcIt, \c OutArcIt and \c InArcIt iterators referencing kpeter@735: ///the changed arc are invalidated. kpeter@73: /// deba@57: ///\warning This functionality cannot be used together with the Snapshot deba@57: ///feature. kpeter@735: void reverseArc(Arc a) { kpeter@735: Node t=target(a); kpeter@735: changeTarget(a,source(a)); kpeter@735: changeSource(a,t); deba@57: } deba@57: deba@57: ///Contract two nodes. deba@57: kpeter@735: ///This function contracts the given two nodes. kpeter@735: ///Node \c v is removed, but instead of deleting its kpeter@735: ///incident arcs, they are joined to node \c u. kpeter@735: ///If the last parameter \c r is \c true (this is the default value), kpeter@735: ///then the newly created loops are removed. deba@57: /// kpeter@735: ///\note The moved arcs are joined to node \c u using changeSource() kpeter@735: ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are kpeter@735: ///invalidated for the outgoing arcs of node \c v and \c InArcIt kpeter@1049: ///iterators are invalidated for the incoming arcs of \c v. alpar@877: ///Moreover all iterators referencing node \c v or the removed kpeter@735: ///loops are also invalidated. Other iterators remain valid. kpeter@73: /// deba@57: ///\warning This functionality cannot be used together with the Snapshot deba@57: ///feature. kpeter@735: void contract(Node u, Node v, bool r = true) deba@57: { kpeter@735: for(OutArcIt e(*this,v);e!=INVALID;) { alpar@209: OutArcIt f=e; alpar@209: ++f; kpeter@735: if(r && target(e)==u) erase(e); kpeter@735: else changeSource(e,u); alpar@209: e=f; deba@57: } kpeter@735: for(InArcIt e(*this,v);e!=INVALID;) { alpar@209: InArcIt f=e; alpar@209: ++f; kpeter@735: if(r && source(e)==u) erase(e); kpeter@735: else changeTarget(e,u); alpar@209: e=f; deba@57: } kpeter@735: erase(v); deba@57: } deba@57: deba@57: ///Split a node. deba@57: kpeter@735: ///This function splits the given node. First, a new node is added kpeter@735: ///to the digraph, then the source of each outgoing arc of node \c n kpeter@735: ///is moved to this new node. kpeter@735: ///If the second parameter \c connect is \c true (this is the default kpeter@735: ///value), then a new arc from node \c n to the newly created node kpeter@735: ///is also added. deba@57: ///\return The newly created node. deba@57: /// kpeter@738: ///\note All iterators remain valid. deba@57: /// kpeter@735: ///\warning This functionality cannot be used together with the kpeter@73: ///Snapshot feature. deba@57: Node split(Node n, bool connect = true) { deba@57: Node b = addNode(); ggab90@1130: _nodes[b.id].first_out=_nodes[n.id].first_out; ggab90@1130: _nodes[n.id].first_out=-1; ggab90@1130: for(int i=_nodes[b.id].first_out; i!=-1; i=_arcs[i].next_out) { ggab90@1130: _arcs[i].source=b.id; deba@57: } deba@57: if (connect) addArc(n,b); deba@57: return b; deba@57: } alpar@209: deba@57: ///Split an arc. deba@57: kpeter@735: ///This function splits the given arc. First, a new node \c v is kpeter@735: ///added to the digraph, then the target node of the original arc kpeter@735: ///is set to \c v. Finally, an arc from \c v to the original target kpeter@735: ///is added. kpeter@735: ///\return The newly created node. kpeter@73: /// kpeter@735: ///\note \c InArcIt iterators referencing the original arc are kpeter@735: ///invalidated. Other iterators remain valid. kpeter@73: /// kpeter@73: ///\warning This functionality cannot be used together with the kpeter@73: ///Snapshot feature. kpeter@735: Node split(Arc a) { kpeter@735: Node v = addNode(); kpeter@735: addArc(v,target(a)); kpeter@735: changeTarget(a,v); kpeter@735: return v; deba@57: } alpar@209: kpeter@735: ///Clear the digraph. kpeter@735: kpeter@735: ///This function erases all nodes and arcs from the digraph. kpeter@735: /// kpeter@787: ///\note All iterators of the digraph are invalidated, of course. kpeter@735: void clear() { kpeter@735: Parent::clear(); kpeter@735: } kpeter@735: kpeter@735: /// Reserve memory for nodes. kpeter@735: kpeter@735: /// Using this function, it is possible to avoid superfluous memory kpeter@735: /// allocation: if you know that the digraph you want to build will kpeter@735: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@735: /// then it is worth reserving space for this amount before starting kpeter@735: /// to build the digraph. kpeter@735: /// \sa reserveArc() ggab90@1130: void reserveNode(int n) { _nodes.reserve(n); }; kpeter@735: kpeter@735: /// Reserve memory for arcs. kpeter@735: kpeter@735: /// Using this function, it is possible to avoid superfluous memory kpeter@735: /// allocation: if you know that the digraph you want to build will kpeter@735: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@735: /// then it is worth reserving space for this amount before starting kpeter@735: /// to build the digraph. kpeter@735: /// \sa reserveNode() ggab90@1130: void reserveArc(int m) { _arcs.reserve(m); }; kpeter@735: deba@57: /// \brief Class to make a snapshot of the digraph and restore kpeter@73: /// it later. deba@57: /// kpeter@73: /// Class to make a snapshot of the digraph and restore it later. deba@57: /// deba@57: /// The newly added nodes and arcs can be removed using the deba@57: /// restore() function. deba@57: /// alpar@877: /// \note After a state is restored, you cannot restore a later state, kpeter@735: /// i.e. you cannot add the removed nodes and arcs again using kpeter@735: /// another Snapshot instance. kpeter@735: /// kpeter@735: /// \warning Node and arc deletions and other modifications (e.g. kpeter@735: /// reversing, contracting, splitting arcs or nodes) cannot be alpar@209: /// restored. These events invalidate the snapshot. kpeter@786: /// However, the arcs and nodes that were added to the digraph after kpeter@735: /// making the current snapshot can be removed without invalidating it. deba@57: class Snapshot { deba@57: protected: deba@57: deba@57: typedef Parent::NodeNotifier NodeNotifier; deba@57: deba@57: class NodeObserverProxy : public NodeNotifier::ObserverBase { deba@57: public: deba@57: deba@57: NodeObserverProxy(Snapshot& _snapshot) deba@57: : snapshot(_snapshot) {} deba@57: deba@57: using NodeNotifier::ObserverBase::attach; deba@57: using NodeNotifier::ObserverBase::detach; deba@57: using NodeNotifier::ObserverBase::attached; alpar@209: deba@57: protected: alpar@209: deba@57: virtual void add(const Node& node) { deba@57: snapshot.addNode(node); deba@57: } deba@57: virtual void add(const std::vector& nodes) { alpar@1146: for (int i = nodes.size() - 1; i >= 0; --i) { deba@57: snapshot.addNode(nodes[i]); deba@57: } deba@57: } deba@57: virtual void erase(const Node& node) { deba@57: snapshot.eraseNode(node); deba@57: } deba@57: virtual void erase(const std::vector& nodes) { deba@57: for (int i = 0; i < int(nodes.size()); ++i) { deba@57: snapshot.eraseNode(nodes[i]); deba@57: } deba@57: } deba@57: virtual void build() { deba@57: Node node; deba@57: std::vector nodes; alpar@209: for (notifier()->first(node); node != INVALID; deba@57: notifier()->next(node)) { deba@57: nodes.push_back(node); deba@57: } deba@57: for (int i = nodes.size() - 1; i >= 0; --i) { deba@57: snapshot.addNode(nodes[i]); deba@57: } deba@57: } deba@57: virtual void clear() { deba@57: Node node; alpar@209: for (notifier()->first(node); node != INVALID; deba@57: notifier()->next(node)) { deba@57: snapshot.eraseNode(node); deba@57: } deba@57: } deba@57: deba@57: Snapshot& snapshot; deba@57: }; deba@57: deba@57: class ArcObserverProxy : public ArcNotifier::ObserverBase { deba@57: public: deba@57: deba@57: ArcObserverProxy(Snapshot& _snapshot) deba@57: : snapshot(_snapshot) {} deba@57: deba@57: using ArcNotifier::ObserverBase::attach; deba@57: using ArcNotifier::ObserverBase::detach; deba@57: using ArcNotifier::ObserverBase::attached; alpar@209: deba@57: protected: deba@57: deba@57: virtual void add(const Arc& arc) { deba@57: snapshot.addArc(arc); deba@57: } deba@57: virtual void add(const std::vector& arcs) { alpar@1146: for (int i = arcs.size() - 1; i >= 0; --i) { deba@57: snapshot.addArc(arcs[i]); deba@57: } deba@57: } deba@57: virtual void erase(const Arc& arc) { deba@57: snapshot.eraseArc(arc); deba@57: } deba@57: virtual void erase(const std::vector& arcs) { deba@57: for (int i = 0; i < int(arcs.size()); ++i) { deba@57: snapshot.eraseArc(arcs[i]); deba@57: } deba@57: } deba@57: virtual void build() { deba@57: Arc arc; deba@57: std::vector arcs; alpar@209: for (notifier()->first(arc); arc != INVALID; deba@57: notifier()->next(arc)) { deba@57: arcs.push_back(arc); deba@57: } deba@57: for (int i = arcs.size() - 1; i >= 0; --i) { deba@57: snapshot.addArc(arcs[i]); deba@57: } deba@57: } deba@57: virtual void clear() { deba@57: Arc arc; alpar@209: for (notifier()->first(arc); arc != INVALID; deba@57: notifier()->next(arc)) { deba@57: snapshot.eraseArc(arc); deba@57: } deba@57: } deba@57: deba@57: Snapshot& snapshot; deba@57: }; alpar@209: deba@57: ListDigraph *digraph; deba@57: deba@57: NodeObserverProxy node_observer_proxy; deba@57: ArcObserverProxy arc_observer_proxy; deba@57: deba@57: std::list added_nodes; deba@57: std::list added_arcs; deba@57: deba@57: deba@57: void addNode(const Node& node) { alpar@209: added_nodes.push_front(node); deba@57: } deba@57: void eraseNode(const Node& node) { alpar@209: std::list::iterator it = deba@57: std::find(added_nodes.begin(), added_nodes.end(), node); deba@57: if (it == added_nodes.end()) { deba@57: clear(); deba@57: arc_observer_proxy.detach(); deba@57: throw NodeNotifier::ImmediateDetach(); deba@57: } else { deba@57: added_nodes.erase(it); deba@57: } deba@57: } deba@57: deba@57: void addArc(const Arc& arc) { alpar@209: added_arcs.push_front(arc); deba@57: } deba@57: void eraseArc(const Arc& arc) { alpar@209: std::list::iterator it = deba@57: std::find(added_arcs.begin(), added_arcs.end(), arc); deba@57: if (it == added_arcs.end()) { deba@57: clear(); alpar@209: node_observer_proxy.detach(); deba@57: throw ArcNotifier::ImmediateDetach(); deba@57: } else { deba@57: added_arcs.erase(it); alpar@209: } deba@57: } deba@57: deba@57: void attach(ListDigraph &_digraph) { alpar@209: digraph = &_digraph; alpar@209: node_observer_proxy.attach(digraph->notifier(Node())); deba@57: arc_observer_proxy.attach(digraph->notifier(Arc())); deba@57: } alpar@209: deba@57: void detach() { alpar@209: node_observer_proxy.detach(); alpar@209: arc_observer_proxy.detach(); deba@57: } deba@57: deba@57: bool attached() const { deba@57: return node_observer_proxy.attached(); deba@57: } deba@57: deba@57: void clear() { deba@57: added_nodes.clear(); alpar@209: added_arcs.clear(); deba@57: } deba@57: deba@57: public: deba@57: deba@57: /// \brief Default constructor. deba@57: /// deba@57: /// Default constructor. kpeter@735: /// You have to call save() to actually make a snapshot. alpar@209: Snapshot() alpar@209: : digraph(0), node_observer_proxy(*this), deba@57: arc_observer_proxy(*this) {} alpar@209: deba@57: /// \brief Constructor that immediately makes a snapshot. alpar@209: /// kpeter@735: /// This constructor immediately makes a snapshot of the given digraph. kpeter@735: Snapshot(ListDigraph &gr) alpar@209: : node_observer_proxy(*this), deba@57: arc_observer_proxy(*this) { kpeter@735: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Make a snapshot. deba@57: /// kpeter@735: /// This function makes a snapshot of the given digraph. kpeter@735: /// It can be called more than once. In case of a repeated deba@57: /// call, the previous snapshot gets lost. kpeter@735: void save(ListDigraph &gr) { deba@57: if (attached()) { deba@57: detach(); deba@57: clear(); deba@57: } kpeter@735: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Undo the changes until the last snapshot. kpeter@735: /// kpeter@735: /// This function undos the changes until the last snapshot kpeter@735: /// created by save() or Snapshot(ListDigraph&). kpeter@740: /// kpeter@740: /// \warning This method invalidates the snapshot, i.e. repeated kpeter@740: /// restoring is not supported unless you call save() again. deba@57: void restore() { alpar@209: detach(); alpar@209: for(std::list::iterator it = added_arcs.begin(); deba@57: it != added_arcs.end(); ++it) { alpar@209: digraph->erase(*it); alpar@209: } alpar@209: for(std::list::iterator it = added_nodes.begin(); deba@57: it != added_nodes.end(); ++it) { alpar@209: digraph->erase(*it); alpar@209: } deba@57: clear(); deba@57: } deba@57: kpeter@735: /// \brief Returns \c true if the snapshot is valid. deba@57: /// kpeter@735: /// This function returns \c true if the snapshot is valid. deba@57: bool valid() const { deba@57: return attached(); deba@57: } deba@57: }; alpar@209: deba@57: }; deba@57: deba@57: ///@} deba@57: deba@57: class ListGraphBase { deba@57: deba@57: protected: deba@57: deba@57: struct NodeT { deba@57: int first_out; deba@57: int prev, next; deba@57: }; alpar@209: deba@57: struct ArcT { deba@57: int target; deba@57: int prev_out, next_out; deba@57: }; deba@57: ggab90@1130: std::vector _nodes; deba@57: deba@57: int first_node; deba@57: deba@57: int first_free_node; deba@57: ggab90@1130: std::vector _arcs; deba@57: deba@57: int first_free_arc; alpar@209: deba@57: public: alpar@209: kpeter@617: typedef ListGraphBase Graph; deba@57: deba@57: class Node { deba@57: friend class ListGraphBase; deba@57: protected: deba@57: deba@57: int id; deba@57: explicit Node(int pid) { id = pid;} deba@57: deba@57: public: deba@57: Node() {} deba@57: Node (Invalid) { id = -1; } deba@57: bool operator==(const Node& node) const {return id == node.id;} deba@57: bool operator!=(const Node& node) const {return id != node.id;} deba@57: bool operator<(const Node& node) const {return id < node.id;} deba@57: }; deba@57: deba@57: class Edge { deba@57: friend class ListGraphBase; deba@57: protected: deba@57: deba@57: int id; deba@57: explicit Edge(int pid) { id = pid;} deba@57: deba@57: public: deba@57: Edge() {} deba@57: Edge (Invalid) { id = -1; } kpeter@73: bool operator==(const Edge& edge) const {return id == edge.id;} kpeter@73: bool operator!=(const Edge& edge) const {return id != edge.id;} kpeter@73: bool operator<(const Edge& edge) const {return id < edge.id;} deba@57: }; deba@57: deba@57: class Arc { deba@57: friend class ListGraphBase; deba@57: protected: deba@57: deba@57: int id; deba@57: explicit Arc(int pid) { id = pid;} deba@57: deba@57: public: kpeter@329: operator Edge() const { kpeter@329: return id != -1 ? edgeFromId(id / 2) : INVALID; deba@238: } deba@57: deba@57: Arc() {} deba@57: Arc (Invalid) { id = -1; } deba@57: bool operator==(const Arc& arc) const {return id == arc.id;} deba@57: bool operator!=(const Arc& arc) const {return id != arc.id;} deba@57: bool operator<(const Arc& arc) const {return id < arc.id;} deba@57: }; deba@57: deba@57: ListGraphBase() ggab90@1130: : _nodes(), first_node(-1), ggab90@1130: first_free_node(-1), _arcs(), first_free_arc(-1) {} ggab90@1130: ggab90@1130: ggab90@1130: int maxNodeId() const { return _nodes.size()-1; } ggab90@1130: int maxEdgeId() const { return _arcs.size() / 2 - 1; } ggab90@1130: int maxArcId() const { return _arcs.size()-1; } ggab90@1130: ggab90@1130: Node source(Arc e) const { return Node(_arcs[e.id ^ 1].target); } ggab90@1130: Node target(Arc e) const { return Node(_arcs[e.id].target); } ggab90@1130: ggab90@1130: Node u(Edge e) const { return Node(_arcs[2 * e.id].target); } ggab90@1130: Node v(Edge e) const { return Node(_arcs[2 * e.id + 1].target); } deba@57: deba@57: static bool direction(Arc e) { deba@57: return (e.id & 1) == 1; deba@57: } deba@57: deba@57: static Arc direct(Edge e, bool d) { deba@57: return Arc(e.id * 2 + (d ? 1 : 0)); deba@57: } deba@57: alpar@209: void first(Node& node) const { deba@57: node.id = first_node; deba@57: } deba@57: deba@57: void next(Node& node) const { ggab90@1130: node.id = _nodes[node.id].next; deba@57: } deba@57: alpar@209: void first(Arc& e) const { deba@57: int n = first_node; ggab90@1130: while (n != -1 && _nodes[n].first_out == -1) { ggab90@1130: n = _nodes[n].next; deba@57: } ggab90@1130: e.id = (n == -1) ? -1 : _nodes[n].first_out; deba@57: } deba@57: deba@57: void next(Arc& e) const { ggab90@1130: if (_arcs[e.id].next_out != -1) { ggab90@1130: e.id = _arcs[e.id].next_out; deba@57: } else { ggab90@1130: int n = _nodes[_arcs[e.id ^ 1].target].next; ggab90@1130: while(n != -1 && _nodes[n].first_out == -1) { ggab90@1130: n = _nodes[n].next; deba@57: } ggab90@1130: e.id = (n == -1) ? -1 : _nodes[n].first_out; alpar@209: } deba@57: } deba@57: alpar@209: void first(Edge& e) const { deba@57: int n = first_node; deba@57: while (n != -1) { ggab90@1130: e.id = _nodes[n].first_out; deba@57: while ((e.id & 1) != 1) { ggab90@1130: e.id = _arcs[e.id].next_out; deba@57: } deba@57: if (e.id != -1) { deba@57: e.id /= 2; deba@57: return; alpar@209: } ggab90@1130: n = _nodes[n].next; deba@57: } deba@57: e.id = -1; deba@57: } deba@57: deba@57: void next(Edge& e) const { ggab90@1130: int n = _arcs[e.id * 2].target; ggab90@1130: e.id = _arcs[(e.id * 2) | 1].next_out; deba@57: while ((e.id & 1) != 1) { ggab90@1130: e.id = _arcs[e.id].next_out; deba@57: } deba@57: if (e.id != -1) { deba@57: e.id /= 2; deba@57: return; alpar@209: } ggab90@1130: n = _nodes[n].next; deba@57: while (n != -1) { ggab90@1130: e.id = _nodes[n].first_out; deba@57: while ((e.id & 1) != 1) { ggab90@1130: e.id = _arcs[e.id].next_out; deba@57: } deba@57: if (e.id != -1) { deba@57: e.id /= 2; deba@57: return; alpar@209: } ggab90@1130: n = _nodes[n].next; deba@57: } deba@57: e.id = -1; deba@57: } deba@57: deba@57: void firstOut(Arc &e, const Node& v) const { ggab90@1130: e.id = _nodes[v.id].first_out; deba@57: } deba@57: void nextOut(Arc &e) const { ggab90@1130: e.id = _arcs[e.id].next_out; deba@57: } deba@57: deba@57: void firstIn(Arc &e, const Node& v) const { ggab90@1130: e.id = ((_nodes[v.id].first_out) ^ 1); deba@57: if (e.id == -2) e.id = -1; deba@57: } deba@57: void nextIn(Arc &e) const { ggab90@1130: e.id = ((_arcs[e.id ^ 1].next_out) ^ 1); deba@57: if (e.id == -2) e.id = -1; deba@57: } deba@57: deba@57: void firstInc(Edge &e, bool& d, const Node& v) const { ggab90@1130: int a = _nodes[v.id].first_out; kpeter@73: if (a != -1 ) { kpeter@73: e.id = a / 2; kpeter@73: d = ((a & 1) == 1); deba@57: } else { deba@57: e.id = -1; deba@57: d = true; deba@57: } deba@57: } deba@57: void nextInc(Edge &e, bool& d) const { ggab90@1130: int a = (_arcs[(e.id * 2) | (d ? 1 : 0)].next_out); kpeter@73: if (a != -1 ) { kpeter@73: e.id = a / 2; kpeter@73: d = ((a & 1) == 1); deba@57: } else { deba@57: e.id = -1; deba@57: d = true; deba@57: } deba@57: } alpar@209: deba@57: static int id(Node v) { return v.id; } deba@57: static int id(Arc e) { return e.id; } deba@57: static int id(Edge e) { return e.id; } deba@57: deba@57: static Node nodeFromId(int id) { return Node(id);} deba@57: static Arc arcFromId(int id) { return Arc(id);} deba@57: static Edge edgeFromId(int id) { return Edge(id);} deba@57: alpar@209: bool valid(Node n) const { ggab90@1130: return n.id >= 0 && n.id < static_cast(_nodes.size()) && ggab90@1130: _nodes[n.id].prev != -2; deba@149: } deba@149: alpar@209: bool valid(Arc a) const { ggab90@1130: return a.id >= 0 && a.id < static_cast(_arcs.size()) && ggab90@1130: _arcs[a.id].prev_out != -2; deba@149: } deba@149: alpar@209: bool valid(Edge e) const { ggab90@1130: return e.id >= 0 && 2 * e.id < static_cast(_arcs.size()) && ggab90@1130: _arcs[2 * e.id].prev_out != -2; deba@149: } deba@149: alpar@209: Node addNode() { deba@57: int n; alpar@209: deba@57: if(first_free_node==-1) { ggab90@1130: n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); deba@57: } else { alpar@209: n = first_free_node; ggab90@1130: first_free_node = _nodes[n].next; deba@57: } alpar@209: ggab90@1130: _nodes[n].next = first_node; ggab90@1130: if (first_node != -1) _nodes[first_node].prev = n; deba@57: first_node = n; ggab90@1130: _nodes[n].prev = -1; ggab90@1130: ggab90@1130: _nodes[n].first_out = -1; alpar@209: deba@57: return Node(n); deba@57: } alpar@209: deba@57: Edge addEdge(Node u, Node v) { alpar@209: int n; deba@57: deba@57: if (first_free_arc == -1) { ggab90@1130: n = _arcs.size(); ggab90@1130: _arcs.push_back(ArcT()); ggab90@1130: _arcs.push_back(ArcT()); deba@57: } else { alpar@209: n = first_free_arc; ggab90@1130: first_free_arc = _arcs[n].next_out; deba@57: } alpar@209: ggab90@1130: _arcs[n].target = u.id; ggab90@1130: _arcs[n | 1].target = v.id; ggab90@1130: ggab90@1130: _arcs[n].next_out = _nodes[v.id].first_out; ggab90@1130: if (_nodes[v.id].first_out != -1) { ggab90@1130: _arcs[_nodes[v.id].first_out].prev_out = n; alpar@209: } ggab90@1130: _arcs[n].prev_out = -1; ggab90@1130: _nodes[v.id].first_out = n; ggab90@1130: ggab90@1130: _arcs[n | 1].next_out = _nodes[u.id].first_out; ggab90@1130: if (_nodes[u.id].first_out != -1) { ggab90@1130: _arcs[_nodes[u.id].first_out].prev_out = (n | 1); deba@57: } ggab90@1130: _arcs[n | 1].prev_out = -1; ggab90@1130: _nodes[u.id].first_out = (n | 1); deba@57: deba@57: return Edge(n / 2); deba@57: } alpar@209: deba@57: void erase(const Node& node) { deba@57: int n = node.id; alpar@209: ggab90@1130: if(_nodes[n].next != -1) { ggab90@1130: _nodes[_nodes[n].next].prev = _nodes[n].prev; deba@57: } alpar@209: ggab90@1130: if(_nodes[n].prev != -1) { ggab90@1130: _nodes[_nodes[n].prev].next = _nodes[n].next; deba@57: } else { ggab90@1130: first_node = _nodes[n].next; deba@57: } alpar@209: ggab90@1130: _nodes[n].next = first_free_node; deba@57: first_free_node = n; ggab90@1130: _nodes[n].prev = -2; deba@57: } alpar@209: kpeter@73: void erase(const Edge& edge) { kpeter@73: int n = edge.id * 2; alpar@209: ggab90@1130: if (_arcs[n].next_out != -1) { ggab90@1130: _arcs[_arcs[n].next_out].prev_out = _arcs[n].prev_out; alpar@209: } deba@57: ggab90@1130: if (_arcs[n].prev_out != -1) { ggab90@1130: _arcs[_arcs[n].prev_out].next_out = _arcs[n].next_out; deba@57: } else { ggab90@1130: _nodes[_arcs[n | 1].target].first_out = _arcs[n].next_out; deba@57: } deba@57: ggab90@1130: if (_arcs[n | 1].next_out != -1) { ggab90@1130: _arcs[_arcs[n | 1].next_out].prev_out = _arcs[n | 1].prev_out; alpar@209: } deba@57: ggab90@1130: if (_arcs[n | 1].prev_out != -1) { ggab90@1130: _arcs[_arcs[n | 1].prev_out].next_out = _arcs[n | 1].next_out; deba@57: } else { ggab90@1130: _nodes[_arcs[n].target].first_out = _arcs[n | 1].next_out; deba@57: } alpar@209: ggab90@1130: _arcs[n].next_out = first_free_arc; alpar@209: first_free_arc = n; ggab90@1130: _arcs[n].prev_out = -2; ggab90@1130: _arcs[n | 1].prev_out = -2; deba@57: deba@57: } deba@57: deba@57: void clear() { ggab90@1130: _arcs.clear(); ggab90@1130: _nodes.clear(); deba@57: first_node = first_free_node = first_free_arc = -1; deba@57: } deba@57: deba@57: protected: deba@57: deba@235: void changeV(Edge e, Node n) { ggab90@1130: if(_arcs[2 * e.id].next_out != -1) { ggab90@1130: _arcs[_arcs[2 * e.id].next_out].prev_out = _arcs[2 * e.id].prev_out; deba@57: } ggab90@1130: if(_arcs[2 * e.id].prev_out != -1) { ggab90@1130: _arcs[_arcs[2 * e.id].prev_out].next_out = ggab90@1130: _arcs[2 * e.id].next_out; deba@57: } else { ggab90@1130: _nodes[_arcs[(2 * e.id) | 1].target].first_out = ggab90@1130: _arcs[2 * e.id].next_out; deba@57: } deba@57: ggab90@1130: if (_nodes[n.id].first_out != -1) { ggab90@1130: _arcs[_nodes[n.id].first_out].prev_out = 2 * e.id; deba@57: } ggab90@1130: _arcs[(2 * e.id) | 1].target = n.id; ggab90@1130: _arcs[2 * e.id].prev_out = -1; ggab90@1130: _arcs[2 * e.id].next_out = _nodes[n.id].first_out; ggab90@1130: _nodes[n.id].first_out = 2 * e.id; deba@57: } deba@57: deba@235: void changeU(Edge e, Node n) { ggab90@1130: if(_arcs[(2 * e.id) | 1].next_out != -1) { ggab90@1130: _arcs[_arcs[(2 * e.id) | 1].next_out].prev_out = ggab90@1130: _arcs[(2 * e.id) | 1].prev_out; deba@57: } ggab90@1130: if(_arcs[(2 * e.id) | 1].prev_out != -1) { ggab90@1130: _arcs[_arcs[(2 * e.id) | 1].prev_out].next_out = ggab90@1130: _arcs[(2 * e.id) | 1].next_out; deba@57: } else { ggab90@1130: _nodes[_arcs[2 * e.id].target].first_out = ggab90@1130: _arcs[(2 * e.id) | 1].next_out; deba@57: } deba@57: ggab90@1130: if (_nodes[n.id].first_out != -1) { ggab90@1130: _arcs[_nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); deba@57: } ggab90@1130: _arcs[2 * e.id].target = n.id; ggab90@1130: _arcs[(2 * e.id) | 1].prev_out = -1; ggab90@1130: _arcs[(2 * e.id) | 1].next_out = _nodes[n.id].first_out; ggab90@1130: _nodes[n.id].first_out = ((2 * e.id) | 1); deba@57: } deba@57: deba@57: }; deba@57: deba@57: typedef GraphExtender ExtendedListGraphBase; deba@57: deba@57: kpeter@73: /// \addtogroup graphs deba@57: /// @{ deba@57: kpeter@73: ///A general undirected graph structure. deba@57: kpeter@735: ///\ref ListGraph is a versatile and fast undirected graph kpeter@735: ///implementation based on linked lists that are stored in alpar@209: ///\c std::vector structures. deba@57: /// kpeter@735: ///This type fully conforms to the \ref concepts::Graph "Graph concept" kpeter@735: ///and it also provides several useful additional functionalities. kpeter@735: ///Most of its member functions and nested classes are documented kpeter@73: ///only in the concept class. kpeter@73: /// kpeter@787: ///This class provides only linear time counting for nodes, edges and arcs. kpeter@787: /// kpeter@73: ///\sa concepts::Graph kpeter@735: ///\sa ListDigraph deba@57: class ListGraph : public ExtendedListGraphBase { kpeter@617: typedef ExtendedListGraphBase Parent; kpeter@617: deba@57: private: kpeter@735: /// Graphs are \e not copy constructible. Use GraphCopy instead. deba@57: ListGraph(const ListGraph &) :ExtendedListGraphBase() {}; kpeter@735: /// \brief Assignment of a graph to another one is \e not allowed. kpeter@735: /// Use GraphCopy instead. deba@57: void operator=(const ListGraph &) {} deba@57: public: deba@57: /// Constructor alpar@209: deba@57: /// Constructor. deba@57: /// deba@57: ListGraph() {} deba@57: alpar@1131: typedef Parent::IncEdgeIt IncEdgeIt; deba@57: kpeter@73: /// \brief Add a new node to the graph. deba@57: /// kpeter@735: /// This function adds a new node to the graph. kpeter@559: /// \return The new node. deba@57: Node addNode() { return Parent::addNode(); } deba@57: kpeter@73: /// \brief Add a new edge to the graph. deba@57: /// kpeter@735: /// This function adds a new edge to the graph between nodes kpeter@735: /// \c u and \c v with inherent orientation from node \c u to kpeter@735: /// node \c v. kpeter@559: /// \return The new edge. kpeter@735: Edge addEdge(Node u, Node v) { kpeter@735: return Parent::addEdge(u, v); deba@57: } deba@234: kpeter@735: ///\brief Erase a node from the graph. deba@234: /// kpeter@787: /// This function erases the given node along with its incident arcs kpeter@787: /// from the graph. kpeter@787: /// kpeter@787: /// \note All iterators referencing the removed node or the incident kpeter@787: /// edges are invalidated, of course. kpeter@735: void erase(Node n) { Parent::erase(n); } kpeter@735: kpeter@735: ///\brief Erase an edge from the graph. deba@234: /// kpeter@735: /// This function erases the given edge from the graph. kpeter@787: /// kpeter@787: /// \note All iterators referencing the removed edge are invalidated, kpeter@787: /// of course. kpeter@735: void erase(Edge e) { Parent::erase(e); } deba@149: /// Node validity check deba@149: kpeter@735: /// This function gives back \c true if the given node is valid, kpeter@735: /// i.e. it is a real node of the graph. deba@149: /// kpeter@735: /// \warning A removed node could become valid again if new nodes are deba@149: /// added to the graph. deba@149: bool valid(Node n) const { return Parent::valid(n); } kpeter@735: /// Edge validity check kpeter@735: kpeter@735: /// This function gives back \c true if the given edge is valid, kpeter@735: /// i.e. it is a real edge of the graph. kpeter@735: /// kpeter@735: /// \warning A removed edge could become valid again if new edges are kpeter@735: /// added to the graph. kpeter@735: bool valid(Edge e) const { return Parent::valid(e); } deba@149: /// Arc validity check deba@149: kpeter@735: /// This function gives back \c true if the given arc is valid, kpeter@735: /// i.e. it is a real arc of the graph. deba@149: /// kpeter@735: /// \warning A removed arc could become valid again if new edges are deba@149: /// added to the graph. deba@149: bool valid(Arc a) const { return Parent::valid(a); } deba@149: kpeter@735: /// \brief Change the first node of an edge. deba@149: /// kpeter@735: /// This function changes the first node of the given edge \c e to \c n. deba@57: /// kpeter@735: ///\note \c EdgeIt and \c ArcIt iterators referencing the kpeter@735: ///changed edge are invalidated and all other iterators whose kpeter@735: ///base node is the changed node are also invalidated. kpeter@73: /// kpeter@73: ///\warning This functionality cannot be used together with the kpeter@73: ///Snapshot feature. deba@235: void changeU(Edge e, Node n) { deba@235: Parent::changeU(e,n); alpar@209: } kpeter@735: /// \brief Change the second node of an edge. deba@57: /// kpeter@735: /// This function changes the second node of the given edge \c e to \c n. deba@57: /// kpeter@735: ///\note \c EdgeIt iterators referencing the changed edge remain kpeter@786: ///valid, but \c ArcIt iterators referencing the changed edge and kpeter@735: ///all other iterators whose base node is the changed node are also kpeter@735: ///invalidated. kpeter@73: /// kpeter@73: ///\warning This functionality cannot be used together with the kpeter@73: ///Snapshot feature. deba@235: void changeV(Edge e, Node n) { deba@235: Parent::changeV(e,n); deba@57: } kpeter@735: deba@57: /// \brief Contract two nodes. deba@57: /// kpeter@735: /// This function contracts the given two nodes. kpeter@735: /// Node \c b is removed, but instead of deleting kpeter@735: /// its incident edges, they are joined to node \c a. kpeter@735: /// If the last parameter \c r is \c true (this is the default value), kpeter@735: /// then the newly created loops are removed. deba@57: /// kpeter@735: /// \note The moved edges are joined to node \c a using changeU() kpeter@735: /// or changeV(), thus all edge and arc iterators whose base node is kpeter@735: /// \c b are invalidated. alpar@877: /// Moreover all iterators referencing node \c b or the removed kpeter@735: /// loops are also invalidated. Other iterators remain valid. kpeter@73: /// kpeter@73: ///\warning This functionality cannot be used together with the kpeter@73: ///Snapshot feature. deba@57: void contract(Node a, Node b, bool r = true) { kpeter@73: for(IncEdgeIt e(*this, b); e!=INVALID;) { alpar@209: IncEdgeIt f = e; ++f; alpar@209: if (r && runningNode(e) == a) { alpar@209: erase(e); deba@235: } else if (u(e) == b) { deba@235: changeU(e, a); alpar@209: } else { deba@235: changeV(e, a); alpar@209: } alpar@209: e = f; deba@57: } deba@57: erase(b); deba@57: } deba@57: kpeter@735: ///Clear the graph. kpeter@735: kpeter@735: ///This function erases all nodes and arcs from the graph. kpeter@735: /// kpeter@787: ///\note All iterators of the graph are invalidated, of course. kpeter@735: void clear() { kpeter@735: Parent::clear(); kpeter@735: } kpeter@617: kpeter@736: /// Reserve memory for nodes. kpeter@736: kpeter@736: /// Using this function, it is possible to avoid superfluous memory kpeter@736: /// allocation: if you know that the graph you want to build will kpeter@736: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@736: /// then it is worth reserving space for this amount before starting kpeter@736: /// to build the graph. kpeter@736: /// \sa reserveEdge() ggab90@1130: void reserveNode(int n) { _nodes.reserve(n); }; kpeter@736: kpeter@736: /// Reserve memory for edges. kpeter@736: kpeter@736: /// Using this function, it is possible to avoid superfluous memory kpeter@736: /// allocation: if you know that the graph you want to build will kpeter@736: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@736: /// then it is worth reserving space for this amount before starting kpeter@736: /// to build the graph. kpeter@736: /// \sa reserveNode() ggab90@1130: void reserveEdge(int m) { _arcs.reserve(2 * m); }; deba@57: kpeter@73: /// \brief Class to make a snapshot of the graph and restore kpeter@73: /// it later. deba@57: /// kpeter@73: /// Class to make a snapshot of the graph and restore it later. deba@57: /// deba@57: /// The newly added nodes and edges can be removed deba@57: /// using the restore() function. deba@57: /// alpar@877: /// \note After a state is restored, you cannot restore a later state, kpeter@735: /// i.e. you cannot add the removed nodes and edges again using kpeter@735: /// another Snapshot instance. kpeter@735: /// kpeter@735: /// \warning Node and edge deletions and other modifications kpeter@735: /// (e.g. changing the end-nodes of edges or contracting nodes) kpeter@735: /// cannot be restored. These events invalidate the snapshot. kpeter@786: /// However, the edges and nodes that were added to the graph after kpeter@735: /// making the current snapshot can be removed without invalidating it. deba@57: class Snapshot { deba@57: protected: deba@57: deba@57: typedef Parent::NodeNotifier NodeNotifier; deba@57: deba@57: class NodeObserverProxy : public NodeNotifier::ObserverBase { deba@57: public: deba@57: deba@57: NodeObserverProxy(Snapshot& _snapshot) deba@57: : snapshot(_snapshot) {} deba@57: deba@57: using NodeNotifier::ObserverBase::attach; deba@57: using NodeNotifier::ObserverBase::detach; deba@57: using NodeNotifier::ObserverBase::attached; alpar@209: deba@57: protected: alpar@209: deba@57: virtual void add(const Node& node) { deba@57: snapshot.addNode(node); deba@57: } deba@57: virtual void add(const std::vector& nodes) { alpar@1146: for (int i = nodes.size() - 1; i >= 0; --i) { deba@57: snapshot.addNode(nodes[i]); deba@57: } deba@57: } deba@57: virtual void erase(const Node& node) { deba@57: snapshot.eraseNode(node); deba@57: } deba@57: virtual void erase(const std::vector& nodes) { deba@57: for (int i = 0; i < int(nodes.size()); ++i) { deba@57: snapshot.eraseNode(nodes[i]); deba@57: } deba@57: } deba@57: virtual void build() { deba@57: Node node; deba@57: std::vector nodes; alpar@209: for (notifier()->first(node); node != INVALID; deba@57: notifier()->next(node)) { deba@57: nodes.push_back(node); deba@57: } deba@57: for (int i = nodes.size() - 1; i >= 0; --i) { deba@57: snapshot.addNode(nodes[i]); deba@57: } deba@57: } deba@57: virtual void clear() { deba@57: Node node; alpar@209: for (notifier()->first(node); node != INVALID; deba@57: notifier()->next(node)) { deba@57: snapshot.eraseNode(node); deba@57: } deba@57: } deba@57: deba@57: Snapshot& snapshot; deba@57: }; deba@57: deba@57: class EdgeObserverProxy : public EdgeNotifier::ObserverBase { deba@57: public: deba@57: deba@57: EdgeObserverProxy(Snapshot& _snapshot) deba@57: : snapshot(_snapshot) {} deba@57: deba@57: using EdgeNotifier::ObserverBase::attach; deba@57: using EdgeNotifier::ObserverBase::detach; deba@57: using EdgeNotifier::ObserverBase::attached; alpar@209: deba@57: protected: deba@57: kpeter@73: virtual void add(const Edge& edge) { kpeter@73: snapshot.addEdge(edge); deba@57: } kpeter@73: virtual void add(const std::vector& edges) { alpar@1146: for (int i = edges.size() - 1; i >= 0; --i) { kpeter@73: snapshot.addEdge(edges[i]); deba@57: } deba@57: } kpeter@73: virtual void erase(const Edge& edge) { kpeter@73: snapshot.eraseEdge(edge); deba@57: } kpeter@73: virtual void erase(const std::vector& edges) { kpeter@73: for (int i = 0; i < int(edges.size()); ++i) { kpeter@73: snapshot.eraseEdge(edges[i]); deba@57: } deba@57: } deba@57: virtual void build() { kpeter@73: Edge edge; kpeter@73: std::vector edges; alpar@209: for (notifier()->first(edge); edge != INVALID; kpeter@73: notifier()->next(edge)) { kpeter@73: edges.push_back(edge); deba@57: } kpeter@73: for (int i = edges.size() - 1; i >= 0; --i) { kpeter@73: snapshot.addEdge(edges[i]); deba@57: } deba@57: } deba@57: virtual void clear() { kpeter@73: Edge edge; alpar@209: for (notifier()->first(edge); edge != INVALID; kpeter@73: notifier()->next(edge)) { kpeter@73: snapshot.eraseEdge(edge); deba@57: } deba@57: } deba@57: deba@57: Snapshot& snapshot; deba@57: }; kpeter@73: kpeter@73: ListGraph *graph; deba@57: deba@57: NodeObserverProxy node_observer_proxy; kpeter@73: EdgeObserverProxy edge_observer_proxy; deba@57: deba@57: std::list added_nodes; kpeter@73: std::list added_edges; deba@57: deba@57: deba@57: void addNode(const Node& node) { alpar@209: added_nodes.push_front(node); deba@57: } deba@57: void eraseNode(const Node& node) { alpar@209: std::list::iterator it = deba@57: std::find(added_nodes.begin(), added_nodes.end(), node); deba@57: if (it == added_nodes.end()) { deba@57: clear(); kpeter@73: edge_observer_proxy.detach(); deba@57: throw NodeNotifier::ImmediateDetach(); deba@57: } else { deba@57: added_nodes.erase(it); deba@57: } deba@57: } deba@57: kpeter@73: void addEdge(const Edge& edge) { alpar@209: added_edges.push_front(edge); deba@57: } kpeter@73: void eraseEdge(const Edge& edge) { alpar@209: std::list::iterator it = kpeter@73: std::find(added_edges.begin(), added_edges.end(), edge); kpeter@73: if (it == added_edges.end()) { deba@57: clear(); deba@57: node_observer_proxy.detach(); deba@57: throw EdgeNotifier::ImmediateDetach(); deba@57: } else { kpeter@73: added_edges.erase(it); kpeter@73: } deba@57: } deba@57: kpeter@73: void attach(ListGraph &_graph) { alpar@209: graph = &_graph; alpar@209: node_observer_proxy.attach(graph->notifier(Node())); kpeter@73: edge_observer_proxy.attach(graph->notifier(Edge())); deba@57: } alpar@209: deba@57: void detach() { alpar@209: node_observer_proxy.detach(); alpar@209: edge_observer_proxy.detach(); deba@57: } deba@57: deba@57: bool attached() const { deba@57: return node_observer_proxy.attached(); deba@57: } deba@57: deba@57: void clear() { deba@57: added_nodes.clear(); alpar@209: added_edges.clear(); deba@57: } deba@57: deba@57: public: deba@57: deba@57: /// \brief Default constructor. deba@57: /// deba@57: /// Default constructor. kpeter@735: /// You have to call save() to actually make a snapshot. alpar@209: Snapshot() alpar@209: : graph(0), node_observer_proxy(*this), kpeter@73: edge_observer_proxy(*this) {} alpar@209: deba@57: /// \brief Constructor that immediately makes a snapshot. alpar@209: /// kpeter@735: /// This constructor immediately makes a snapshot of the given graph. kpeter@735: Snapshot(ListGraph &gr) alpar@209: : node_observer_proxy(*this), kpeter@73: edge_observer_proxy(*this) { kpeter@735: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Make a snapshot. deba@57: /// kpeter@735: /// This function makes a snapshot of the given graph. kpeter@735: /// It can be called more than once. In case of a repeated deba@57: /// call, the previous snapshot gets lost. kpeter@735: void save(ListGraph &gr) { deba@57: if (attached()) { deba@57: detach(); deba@57: clear(); deba@57: } kpeter@735: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Undo the changes until the last snapshot. kpeter@735: /// kpeter@735: /// This function undos the changes until the last snapshot kpeter@735: /// created by save() or Snapshot(ListGraph&). kpeter@740: /// kpeter@740: /// \warning This method invalidates the snapshot, i.e. repeated kpeter@740: /// restoring is not supported unless you call save() again. deba@57: void restore() { alpar@209: detach(); alpar@209: for(std::list::iterator it = added_edges.begin(); kpeter@73: it != added_edges.end(); ++it) { alpar@209: graph->erase(*it); alpar@209: } alpar@209: for(std::list::iterator it = added_nodes.begin(); deba@57: it != added_nodes.end(); ++it) { alpar@209: graph->erase(*it); alpar@209: } deba@57: clear(); deba@57: } deba@57: kpeter@735: /// \brief Returns \c true if the snapshot is valid. deba@57: /// kpeter@735: /// This function returns \c true if the snapshot is valid. deba@57: bool valid() const { deba@57: return attached(); deba@57: } deba@57: }; deba@57: }; alpar@209: alpar@209: /// @} alpar@1147: alpar@1147: class ListBpGraphBase { alpar@1147: alpar@1147: protected: alpar@1147: alpar@1147: struct NodeT { alpar@1147: int first_out; alpar@1147: int prev, next; alpar@1147: int partition_prev, partition_next; alpar@1147: int partition_index; alpar@1147: bool red; alpar@1147: }; alpar@1147: alpar@1147: struct ArcT { alpar@1147: int target; alpar@1147: int prev_out, next_out; alpar@1147: }; alpar@1147: ggab90@1130: std::vector _nodes; alpar@1147: alpar@1147: int first_node, first_red, first_blue; alpar@1147: int max_red, max_blue; alpar@1147: alpar@1147: int first_free_red, first_free_blue; alpar@1147: ggab90@1130: std::vector _arcs; alpar@1147: alpar@1147: int first_free_arc; alpar@1147: alpar@1147: public: alpar@1147: alpar@1147: typedef ListBpGraphBase BpGraph; alpar@1147: alpar@1147: class Node { alpar@1147: friend class ListBpGraphBase; alpar@1147: protected: alpar@1147: alpar@1147: int id; alpar@1147: explicit Node(int pid) { id = pid;} alpar@1147: alpar@1147: public: alpar@1147: Node() {} alpar@1147: Node (Invalid) { id = -1; } alpar@1147: bool operator==(const Node& node) const {return id == node.id;} alpar@1147: bool operator!=(const Node& node) const {return id != node.id;} alpar@1147: bool operator<(const Node& node) const {return id < node.id;} alpar@1147: }; alpar@1147: alpar@1147: class RedNode : public Node { alpar@1147: friend class ListBpGraphBase; alpar@1147: protected: alpar@1147: alpar@1147: explicit RedNode(int pid) : Node(pid) {} alpar@1147: alpar@1147: public: alpar@1147: RedNode() {} alpar@1147: RedNode(const RedNode& node) : Node(node) {} alpar@1147: RedNode(Invalid) : Node(INVALID){} alpar@1147: }; alpar@1147: alpar@1147: class BlueNode : public Node { alpar@1147: friend class ListBpGraphBase; alpar@1147: protected: alpar@1147: alpar@1147: explicit BlueNode(int pid) : Node(pid) {} alpar@1147: alpar@1147: public: alpar@1147: BlueNode() {} alpar@1147: BlueNode(const BlueNode& node) : Node(node) {} alpar@1147: BlueNode(Invalid) : Node(INVALID){} alpar@1147: }; alpar@1147: alpar@1147: class Edge { alpar@1147: friend class ListBpGraphBase; alpar@1147: protected: alpar@1147: alpar@1147: int id; alpar@1147: explicit Edge(int pid) { id = pid;} alpar@1147: alpar@1147: public: alpar@1147: Edge() {} alpar@1147: Edge (Invalid) { id = -1; } alpar@1147: bool operator==(const Edge& edge) const {return id == edge.id;} alpar@1147: bool operator!=(const Edge& edge) const {return id != edge.id;} alpar@1147: bool operator<(const Edge& edge) const {return id < edge.id;} alpar@1147: }; alpar@1147: alpar@1147: class Arc { alpar@1147: friend class ListBpGraphBase; alpar@1147: protected: alpar@1147: alpar@1147: int id; alpar@1147: explicit Arc(int pid) { id = pid;} alpar@1147: alpar@1147: public: alpar@1147: operator Edge() const { alpar@1147: return id != -1 ? edgeFromId(id / 2) : INVALID; alpar@1147: } alpar@1147: alpar@1147: Arc() {} alpar@1147: Arc (Invalid) { id = -1; } alpar@1147: bool operator==(const Arc& arc) const {return id == arc.id;} alpar@1147: bool operator!=(const Arc& arc) const {return id != arc.id;} alpar@1147: bool operator<(const Arc& arc) const {return id < arc.id;} alpar@1147: }; alpar@1147: alpar@1147: ListBpGraphBase() ggab90@1130: : _nodes(), first_node(-1), alpar@1147: first_red(-1), first_blue(-1), alpar@1147: max_red(-1), max_blue(-1), alpar@1147: first_free_red(-1), first_free_blue(-1), ggab90@1130: _arcs(), first_free_arc(-1) {} ggab90@1130: ggab90@1130: ggab90@1130: bool red(Node n) const { return _nodes[n.id].red; } ggab90@1130: bool blue(Node n) const { return !_nodes[n.id].red; } alpar@1147: alpar@1147: static RedNode asRedNodeUnsafe(Node n) { return RedNode(n.id); } alpar@1147: static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n.id); } alpar@1147: ggab90@1130: int maxNodeId() const { return _nodes.size()-1; } alpar@1147: int maxRedId() const { return max_red; } alpar@1147: int maxBlueId() const { return max_blue; } ggab90@1130: int maxEdgeId() const { return _arcs.size() / 2 - 1; } ggab90@1130: int maxArcId() const { return _arcs.size()-1; } ggab90@1130: ggab90@1130: Node source(Arc e) const { return Node(_arcs[e.id ^ 1].target); } ggab90@1130: Node target(Arc e) const { return Node(_arcs[e.id].target); } alpar@1147: alpar@1147: RedNode redNode(Edge e) const { ggab90@1130: return RedNode(_arcs[2 * e.id].target); alpar@1147: } alpar@1147: BlueNode blueNode(Edge e) const { ggab90@1130: return BlueNode(_arcs[2 * e.id + 1].target); alpar@1147: } alpar@1147: alpar@1147: static bool direction(Arc e) { alpar@1147: return (e.id & 1) == 1; alpar@1147: } alpar@1147: alpar@1147: static Arc direct(Edge e, bool d) { alpar@1147: return Arc(e.id * 2 + (d ? 1 : 0)); alpar@1147: } alpar@1147: alpar@1147: void first(Node& node) const { alpar@1147: node.id = first_node; alpar@1147: } alpar@1147: alpar@1147: void next(Node& node) const { ggab90@1130: node.id = _nodes[node.id].next; alpar@1147: } alpar@1147: alpar@1147: void first(RedNode& node) const { alpar@1147: node.id = first_red; alpar@1147: } alpar@1147: alpar@1147: void next(RedNode& node) const { ggab90@1130: node.id = _nodes[node.id].partition_next; alpar@1147: } alpar@1147: alpar@1147: void first(BlueNode& node) const { alpar@1147: node.id = first_blue; alpar@1147: } alpar@1147: alpar@1147: void next(BlueNode& node) const { ggab90@1130: node.id = _nodes[node.id].partition_next; alpar@1147: } alpar@1147: alpar@1147: void first(Arc& e) const { alpar@1147: int n = first_node; ggab90@1130: while (n != -1 && _nodes[n].first_out == -1) { ggab90@1130: n = _nodes[n].next; alpar@1147: } ggab90@1130: e.id = (n == -1) ? -1 : _nodes[n].first_out; alpar@1147: } alpar@1147: alpar@1147: void next(Arc& e) const { ggab90@1130: if (_arcs[e.id].next_out != -1) { ggab90@1130: e.id = _arcs[e.id].next_out; alpar@1147: } else { ggab90@1130: int n = _nodes[_arcs[e.id ^ 1].target].next; ggab90@1130: while(n != -1 && _nodes[n].first_out == -1) { ggab90@1130: n = _nodes[n].next; alpar@1147: } ggab90@1130: e.id = (n == -1) ? -1 : _nodes[n].first_out; alpar@1147: } alpar@1147: } alpar@1147: alpar@1147: void first(Edge& e) const { alpar@1147: int n = first_node; alpar@1147: while (n != -1) { ggab90@1130: e.id = _nodes[n].first_out; alpar@1147: while ((e.id & 1) != 1) { ggab90@1130: e.id = _arcs[e.id].next_out; alpar@1147: } alpar@1147: if (e.id != -1) { alpar@1147: e.id /= 2; alpar@1147: return; alpar@1147: } ggab90@1130: n = _nodes[n].next; alpar@1147: } alpar@1147: e.id = -1; alpar@1147: } alpar@1147: alpar@1147: void next(Edge& e) const { ggab90@1130: int n = _arcs[e.id * 2].target; ggab90@1130: e.id = _arcs[(e.id * 2) | 1].next_out; alpar@1147: while ((e.id & 1) != 1) { ggab90@1130: e.id = _arcs[e.id].next_out; alpar@1147: } alpar@1147: if (e.id != -1) { alpar@1147: e.id /= 2; alpar@1147: return; alpar@1147: } ggab90@1130: n = _nodes[n].next; alpar@1147: while (n != -1) { ggab90@1130: e.id = _nodes[n].first_out; alpar@1147: while ((e.id & 1) != 1) { ggab90@1130: e.id = _arcs[e.id].next_out; alpar@1147: } alpar@1147: if (e.id != -1) { alpar@1147: e.id /= 2; alpar@1147: return; alpar@1147: } ggab90@1130: n = _nodes[n].next; alpar@1147: } alpar@1147: e.id = -1; alpar@1147: } alpar@1147: alpar@1147: void firstOut(Arc &e, const Node& v) const { ggab90@1130: e.id = _nodes[v.id].first_out; alpar@1147: } alpar@1147: void nextOut(Arc &e) const { ggab90@1130: e.id = _arcs[e.id].next_out; alpar@1147: } alpar@1147: alpar@1147: void firstIn(Arc &e, const Node& v) const { ggab90@1130: e.id = ((_nodes[v.id].first_out) ^ 1); alpar@1147: if (e.id == -2) e.id = -1; alpar@1147: } alpar@1147: void nextIn(Arc &e) const { ggab90@1130: e.id = ((_arcs[e.id ^ 1].next_out) ^ 1); alpar@1147: if (e.id == -2) e.id = -1; alpar@1147: } alpar@1147: alpar@1147: void firstInc(Edge &e, bool& d, const Node& v) const { ggab90@1130: int a = _nodes[v.id].first_out; alpar@1147: if (a != -1 ) { alpar@1147: e.id = a / 2; alpar@1147: d = ((a & 1) == 1); alpar@1147: } else { alpar@1147: e.id = -1; alpar@1147: d = true; alpar@1147: } alpar@1147: } alpar@1147: void nextInc(Edge &e, bool& d) const { ggab90@1130: int a = (_arcs[(e.id * 2) | (d ? 1 : 0)].next_out); alpar@1147: if (a != -1 ) { alpar@1147: e.id = a / 2; alpar@1147: d = ((a & 1) == 1); alpar@1147: } else { alpar@1147: e.id = -1; alpar@1147: d = true; alpar@1147: } alpar@1147: } alpar@1147: alpar@1147: static int id(Node v) { return v.id; } ggab90@1130: int id(RedNode v) const { return _nodes[v.id].partition_index; } ggab90@1130: int id(BlueNode v) const { return _nodes[v.id].partition_index; } alpar@1147: static int id(Arc e) { return e.id; } alpar@1147: static int id(Edge e) { return e.id; } alpar@1147: alpar@1147: static Node nodeFromId(int id) { return Node(id);} alpar@1147: static Arc arcFromId(int id) { return Arc(id);} alpar@1147: static Edge edgeFromId(int id) { return Edge(id);} alpar@1147: alpar@1147: bool valid(Node n) const { ggab90@1130: return n.id >= 0 && n.id < static_cast(_nodes.size()) && ggab90@1130: _nodes[n.id].prev != -2; alpar@1147: } alpar@1147: alpar@1147: bool valid(Arc a) const { ggab90@1130: return a.id >= 0 && a.id < static_cast(_arcs.size()) && ggab90@1130: _arcs[a.id].prev_out != -2; alpar@1147: } alpar@1147: alpar@1147: bool valid(Edge e) const { ggab90@1130: return e.id >= 0 && 2 * e.id < static_cast(_arcs.size()) && ggab90@1130: _arcs[2 * e.id].prev_out != -2; alpar@1147: } alpar@1147: alpar@1147: RedNode addRedNode() { alpar@1147: int n; alpar@1147: alpar@1147: if(first_free_red==-1) { ggab90@1130: n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); ggab90@1130: _nodes[n].partition_index = ++max_red; ggab90@1130: _nodes[n].red = true; alpar@1147: } else { alpar@1147: n = first_free_red; ggab90@1130: first_free_red = _nodes[n].next; alpar@1147: } alpar@1147: ggab90@1130: _nodes[n].next = first_node; ggab90@1130: if (first_node != -1) _nodes[first_node].prev = n; alpar@1147: first_node = n; ggab90@1130: _nodes[n].prev = -1; ggab90@1130: ggab90@1130: _nodes[n].partition_next = first_red; ggab90@1130: if (first_red != -1) _nodes[first_red].partition_prev = n; alpar@1147: first_red = n; ggab90@1130: _nodes[n].partition_prev = -1; ggab90@1130: ggab90@1130: _nodes[n].first_out = -1; alpar@1147: alpar@1147: return RedNode(n); alpar@1147: } alpar@1147: alpar@1147: BlueNode addBlueNode() { alpar@1147: int n; alpar@1147: alpar@1147: if(first_free_blue==-1) { ggab90@1130: n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); ggab90@1130: _nodes[n].partition_index = ++max_blue; ggab90@1130: _nodes[n].red = false; alpar@1147: } else { alpar@1147: n = first_free_blue; ggab90@1130: first_free_blue = _nodes[n].next; alpar@1147: } alpar@1147: ggab90@1130: _nodes[n].next = first_node; ggab90@1130: if (first_node != -1) _nodes[first_node].prev = n; alpar@1147: first_node = n; ggab90@1130: _nodes[n].prev = -1; ggab90@1130: ggab90@1130: _nodes[n].partition_next = first_blue; ggab90@1130: if (first_blue != -1) _nodes[first_blue].partition_prev = n; alpar@1147: first_blue = n; ggab90@1130: _nodes[n].partition_prev = -1; ggab90@1130: ggab90@1130: _nodes[n].first_out = -1; alpar@1147: alpar@1147: return BlueNode(n); alpar@1147: } alpar@1147: alpar@1147: Edge addEdge(Node u, Node v) { alpar@1147: int n; alpar@1147: alpar@1147: if (first_free_arc == -1) { ggab90@1130: n = _arcs.size(); ggab90@1130: _arcs.push_back(ArcT()); ggab90@1130: _arcs.push_back(ArcT()); alpar@1147: } else { alpar@1147: n = first_free_arc; ggab90@1130: first_free_arc = _arcs[n].next_out; alpar@1147: } alpar@1147: ggab90@1130: _arcs[n].target = u.id; ggab90@1130: _arcs[n | 1].target = v.id; ggab90@1130: ggab90@1130: _arcs[n].next_out = _nodes[v.id].first_out; ggab90@1130: if (_nodes[v.id].first_out != -1) { ggab90@1130: _arcs[_nodes[v.id].first_out].prev_out = n; alpar@1147: } ggab90@1130: _arcs[n].prev_out = -1; ggab90@1130: _nodes[v.id].first_out = n; ggab90@1130: ggab90@1130: _arcs[n | 1].next_out = _nodes[u.id].first_out; ggab90@1130: if (_nodes[u.id].first_out != -1) { ggab90@1130: _arcs[_nodes[u.id].first_out].prev_out = (n | 1); alpar@1147: } ggab90@1130: _arcs[n | 1].prev_out = -1; ggab90@1130: _nodes[u.id].first_out = (n | 1); alpar@1147: alpar@1147: return Edge(n / 2); alpar@1147: } alpar@1147: alpar@1147: void erase(const Node& node) { alpar@1147: int n = node.id; alpar@1147: ggab90@1130: if(_nodes[n].next != -1) { ggab90@1130: _nodes[_nodes[n].next].prev = _nodes[n].prev; alpar@1147: } alpar@1147: ggab90@1130: if(_nodes[n].prev != -1) { ggab90@1130: _nodes[_nodes[n].prev].next = _nodes[n].next; alpar@1147: } else { ggab90@1130: first_node = _nodes[n].next; alpar@1147: } alpar@1147: ggab90@1130: if (_nodes[n].partition_next != -1) { ggab90@1130: _nodes[_nodes[n].partition_next].partition_prev = _nodes[n].partition_prev; alpar@1147: } alpar@1147: ggab90@1130: if (_nodes[n].partition_prev != -1) { ggab90@1130: _nodes[_nodes[n].partition_prev].partition_next = _nodes[n].partition_next; alpar@1147: } else { ggab90@1130: if (_nodes[n].red) { ggab90@1130: first_red = _nodes[n].partition_next; alpar@1147: } else { ggab90@1130: first_blue = _nodes[n].partition_next; alpar@1147: } alpar@1147: } alpar@1147: ggab90@1130: if (_nodes[n].red) { ggab90@1130: _nodes[n].next = first_free_red; alpar@1147: first_free_red = n; alpar@1147: } else { ggab90@1130: _nodes[n].next = first_free_blue; alpar@1147: first_free_blue = n; alpar@1147: } ggab90@1130: _nodes[n].prev = -2; alpar@1147: } alpar@1147: alpar@1147: void erase(const Edge& edge) { alpar@1147: int n = edge.id * 2; alpar@1147: ggab90@1130: if (_arcs[n].next_out != -1) { ggab90@1130: _arcs[_arcs[n].next_out].prev_out = _arcs[n].prev_out; alpar@1147: } alpar@1147: ggab90@1130: if (_arcs[n].prev_out != -1) { ggab90@1130: _arcs[_arcs[n].prev_out].next_out = _arcs[n].next_out; alpar@1147: } else { ggab90@1130: _nodes[_arcs[n | 1].target].first_out = _arcs[n].next_out; alpar@1147: } alpar@1147: ggab90@1130: if (_arcs[n | 1].next_out != -1) { ggab90@1130: _arcs[_arcs[n | 1].next_out].prev_out = _arcs[n | 1].prev_out; alpar@1147: } alpar@1147: ggab90@1130: if (_arcs[n | 1].prev_out != -1) { ggab90@1130: _arcs[_arcs[n | 1].prev_out].next_out = _arcs[n | 1].next_out; alpar@1147: } else { ggab90@1130: _nodes[_arcs[n].target].first_out = _arcs[n | 1].next_out; alpar@1147: } alpar@1147: ggab90@1130: _arcs[n].next_out = first_free_arc; alpar@1147: first_free_arc = n; ggab90@1130: _arcs[n].prev_out = -2; ggab90@1130: _arcs[n | 1].prev_out = -2; alpar@1147: alpar@1147: } alpar@1147: alpar@1147: void clear() { ggab90@1130: _arcs.clear(); ggab90@1130: _nodes.clear(); alpar@1147: first_node = first_free_arc = first_red = first_blue = alpar@1147: max_red = max_blue = first_free_red = first_free_blue = -1; alpar@1147: } alpar@1147: alpar@1147: protected: alpar@1147: alpar@1147: void changeRed(Edge e, RedNode n) { ggab90@1130: if(_arcs[(2 * e.id) | 1].next_out != -1) { ggab90@1130: _arcs[_arcs[(2 * e.id) | 1].next_out].prev_out = ggab90@1130: _arcs[(2 * e.id) | 1].prev_out; alpar@1147: } ggab90@1130: if(_arcs[(2 * e.id) | 1].prev_out != -1) { ggab90@1130: _arcs[_arcs[(2 * e.id) | 1].prev_out].next_out = ggab90@1130: _arcs[(2 * e.id) | 1].next_out; alpar@1147: } else { ggab90@1130: _nodes[_arcs[2 * e.id].target].first_out = ggab90@1130: _arcs[(2 * e.id) | 1].next_out; alpar@1147: } alpar@1147: ggab90@1130: if (_nodes[n.id].first_out != -1) { ggab90@1130: _arcs[_nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); alpar@1147: } ggab90@1130: _arcs[2 * e.id].target = n.id; ggab90@1130: _arcs[(2 * e.id) | 1].prev_out = -1; ggab90@1130: _arcs[(2 * e.id) | 1].next_out = _nodes[n.id].first_out; ggab90@1130: _nodes[n.id].first_out = ((2 * e.id) | 1); alpar@1147: } alpar@1147: alpar@1147: void changeBlue(Edge e, BlueNode n) { ggab90@1130: if(_arcs[2 * e.id].next_out != -1) { ggab90@1130: _arcs[_arcs[2 * e.id].next_out].prev_out = _arcs[2 * e.id].prev_out; alpar@1147: } ggab90@1130: if(_arcs[2 * e.id].prev_out != -1) { ggab90@1130: _arcs[_arcs[2 * e.id].prev_out].next_out = ggab90@1130: _arcs[2 * e.id].next_out; alpar@1147: } else { ggab90@1130: _nodes[_arcs[(2 * e.id) | 1].target].first_out = ggab90@1130: _arcs[2 * e.id].next_out; alpar@1147: } alpar@1147: ggab90@1130: if (_nodes[n.id].first_out != -1) { ggab90@1130: _arcs[_nodes[n.id].first_out].prev_out = 2 * e.id; alpar@1147: } ggab90@1130: _arcs[(2 * e.id) | 1].target = n.id; ggab90@1130: _arcs[2 * e.id].prev_out = -1; ggab90@1130: _arcs[2 * e.id].next_out = _nodes[n.id].first_out; ggab90@1130: _nodes[n.id].first_out = 2 * e.id; alpar@1147: } alpar@1147: alpar@1147: }; alpar@1147: alpar@1147: typedef BpGraphExtender ExtendedListBpGraphBase; alpar@1147: alpar@1147: alpar@1147: /// \addtogroup graphs alpar@1147: /// @{ alpar@1147: alpar@1147: ///A general undirected graph structure. alpar@1147: alpar@1147: ///\ref ListBpGraph is a versatile and fast undirected graph alpar@1147: ///implementation based on linked lists that are stored in alpar@1147: ///\c std::vector structures. alpar@1147: /// alpar@1147: ///This type fully conforms to the \ref concepts::BpGraph "BpGraph concept" alpar@1147: ///and it also provides several useful additional functionalities. alpar@1147: ///Most of its member functions and nested classes are documented alpar@1147: ///only in the concept class. alpar@1147: /// alpar@1147: ///This class provides only linear time counting for nodes, edges and arcs. alpar@1147: /// alpar@1147: ///\sa concepts::BpGraph alpar@1147: ///\sa ListDigraph alpar@1147: class ListBpGraph : public ExtendedListBpGraphBase { alpar@1147: typedef ExtendedListBpGraphBase Parent; alpar@1147: alpar@1147: private: alpar@1147: /// BpGraphs are \e not copy constructible. Use BpGraphCopy instead. alpar@1147: ListBpGraph(const ListBpGraph &) :ExtendedListBpGraphBase() {}; alpar@1147: /// \brief Assignment of a graph to another one is \e not allowed. alpar@1147: /// Use BpGraphCopy instead. alpar@1147: void operator=(const ListBpGraph &) {} alpar@1147: public: alpar@1147: /// Constructor alpar@1147: alpar@1147: /// Constructor. alpar@1147: /// alpar@1147: ListBpGraph() {} alpar@1147: alpar@1131: typedef Parent::IncEdgeIt IncEdgeIt; alpar@1147: alpar@1147: /// \brief Add a new red node to the graph. alpar@1147: /// alpar@1147: /// This function adds a red new node to the graph. alpar@1147: /// \return The new node. alpar@1147: RedNode addRedNode() { return Parent::addRedNode(); } alpar@1147: alpar@1147: /// \brief Add a new blue node to the graph. alpar@1147: /// alpar@1147: /// This function adds a blue new node to the graph. alpar@1147: /// \return The new node. alpar@1147: BlueNode addBlueNode() { return Parent::addBlueNode(); } alpar@1147: alpar@1147: /// \brief Add a new edge to the graph. alpar@1147: /// alpar@1147: /// This function adds a new edge to the graph between nodes alpar@1147: /// \c u and \c v with inherent orientation from node \c u to alpar@1147: /// node \c v. alpar@1147: /// \return The new edge. alpar@1147: Edge addEdge(RedNode u, BlueNode v) { alpar@1147: return Parent::addEdge(u, v); alpar@1147: } alpar@1147: Edge addEdge(BlueNode v, RedNode u) { alpar@1147: return Parent::addEdge(u, v); alpar@1147: } alpar@1147: alpar@1147: ///\brief Erase a node from the graph. alpar@1147: /// alpar@1147: /// This function erases the given node along with its incident arcs alpar@1147: /// from the graph. alpar@1147: /// alpar@1147: /// \note All iterators referencing the removed node or the incident alpar@1147: /// edges are invalidated, of course. alpar@1147: void erase(Node n) { Parent::erase(n); } alpar@1147: alpar@1147: ///\brief Erase an edge from the graph. alpar@1147: /// alpar@1147: /// This function erases the given edge from the graph. alpar@1147: /// alpar@1147: /// \note All iterators referencing the removed edge are invalidated, alpar@1147: /// of course. alpar@1147: void erase(Edge e) { Parent::erase(e); } alpar@1147: /// Node validity check alpar@1147: alpar@1147: /// This function gives back \c true if the given node is valid, alpar@1147: /// i.e. it is a real node of the graph. alpar@1147: /// alpar@1147: /// \warning A removed node could become valid again if new nodes are alpar@1147: /// added to the graph. alpar@1147: bool valid(Node n) const { return Parent::valid(n); } alpar@1147: /// Edge validity check alpar@1147: alpar@1147: /// This function gives back \c true if the given edge is valid, alpar@1147: /// i.e. it is a real edge of the graph. alpar@1147: /// alpar@1147: /// \warning A removed edge could become valid again if new edges are alpar@1147: /// added to the graph. alpar@1147: bool valid(Edge e) const { return Parent::valid(e); } alpar@1147: /// Arc validity check alpar@1147: alpar@1147: /// This function gives back \c true if the given arc is valid, alpar@1147: /// i.e. it is a real arc of the graph. alpar@1147: /// alpar@1147: /// \warning A removed arc could become valid again if new edges are alpar@1147: /// added to the graph. alpar@1147: bool valid(Arc a) const { return Parent::valid(a); } alpar@1147: alpar@1147: /// \brief Change the red node of an edge. alpar@1147: /// alpar@1147: /// This function changes the red node of the given edge \c e to \c n. alpar@1147: /// alpar@1147: ///\note \c EdgeIt and \c ArcIt iterators referencing the alpar@1147: ///changed edge are invalidated and all other iterators whose alpar@1147: ///base node is the changed node are also invalidated. alpar@1147: /// alpar@1147: ///\warning This functionality cannot be used together with the alpar@1147: ///Snapshot feature. alpar@1147: void changeRed(Edge e, RedNode n) { alpar@1147: Parent::changeRed(e, n); alpar@1147: } alpar@1147: /// \brief Change the blue node of an edge. alpar@1147: /// alpar@1147: /// This function changes the blue node of the given edge \c e to \c n. alpar@1147: /// alpar@1147: ///\note \c EdgeIt iterators referencing the changed edge remain alpar@1147: ///valid, but \c ArcIt iterators referencing the changed edge and alpar@1147: ///all other iterators whose base node is the changed node are also alpar@1147: ///invalidated. alpar@1147: /// alpar@1147: ///\warning This functionality cannot be used together with the alpar@1147: ///Snapshot feature. alpar@1147: void changeBlue(Edge e, BlueNode n) { alpar@1147: Parent::changeBlue(e, n); alpar@1147: } alpar@1147: alpar@1147: ///Clear the graph. alpar@1147: alpar@1147: ///This function erases all nodes and arcs from the graph. alpar@1147: /// alpar@1147: ///\note All iterators of the graph are invalidated, of course. alpar@1147: void clear() { alpar@1147: Parent::clear(); alpar@1147: } alpar@1147: alpar@1147: /// Reserve memory for nodes. alpar@1147: alpar@1147: /// Using this function, it is possible to avoid superfluous memory alpar@1147: /// allocation: if you know that the graph you want to build will alpar@1147: /// be large (e.g. it will contain millions of nodes and/or edges), alpar@1147: /// then it is worth reserving space for this amount before starting alpar@1147: /// to build the graph. alpar@1147: /// \sa reserveEdge() ggab90@1130: void reserveNode(int n) { _nodes.reserve(n); }; alpar@1147: alpar@1147: /// Reserve memory for edges. alpar@1147: alpar@1147: /// Using this function, it is possible to avoid superfluous memory alpar@1147: /// allocation: if you know that the graph you want to build will alpar@1147: /// be large (e.g. it will contain millions of nodes and/or edges), alpar@1147: /// then it is worth reserving space for this amount before starting alpar@1147: /// to build the graph. alpar@1147: /// \sa reserveNode() ggab90@1130: void reserveEdge(int m) { _arcs.reserve(2 * m); }; alpar@1147: alpar@1147: /// \brief Class to make a snapshot of the graph and restore alpar@1147: /// it later. alpar@1147: /// alpar@1147: /// Class to make a snapshot of the graph and restore it later. alpar@1147: /// alpar@1147: /// The newly added nodes and edges can be removed alpar@1147: /// using the restore() function. alpar@1147: /// alpar@1147: /// \note After a state is restored, you cannot restore a later state, alpar@1147: /// i.e. you cannot add the removed nodes and edges again using alpar@1147: /// another Snapshot instance. alpar@1147: /// alpar@1147: /// \warning Node and edge deletions and other modifications alpar@1147: /// (e.g. changing the end-nodes of edges or contracting nodes) alpar@1147: /// cannot be restored. These events invalidate the snapshot. alpar@1147: /// However, the edges and nodes that were added to the graph after alpar@1147: /// making the current snapshot can be removed without invalidating it. alpar@1147: class Snapshot { alpar@1147: protected: alpar@1147: alpar@1147: typedef Parent::NodeNotifier NodeNotifier; alpar@1147: alpar@1147: class NodeObserverProxy : public NodeNotifier::ObserverBase { alpar@1147: public: alpar@1147: alpar@1147: NodeObserverProxy(Snapshot& _snapshot) alpar@1147: : snapshot(_snapshot) {} alpar@1147: alpar@1147: using NodeNotifier::ObserverBase::attach; alpar@1147: using NodeNotifier::ObserverBase::detach; alpar@1147: using NodeNotifier::ObserverBase::attached; alpar@1147: alpar@1147: protected: alpar@1147: alpar@1147: virtual void add(const Node& node) { alpar@1147: snapshot.addNode(node); alpar@1147: } alpar@1147: virtual void add(const std::vector& nodes) { alpar@1148: for (int i = nodes.size() - 1; i >= 0; --i) { alpar@877: snapshot.addNode(nodes[i]); alpar@877: } alpar@877: } alpar@877: virtual void erase(const Node& node) { alpar@877: snapshot.eraseNode(node); alpar@877: } alpar@877: virtual void erase(const std::vector& nodes) { alpar@877: for (int i = 0; i < int(nodes.size()); ++i) { alpar@877: snapshot.eraseNode(nodes[i]); alpar@877: } alpar@877: } alpar@877: virtual void build() { alpar@877: Node node; alpar@877: std::vector nodes; alpar@877: for (notifier()->first(node); node != INVALID; alpar@877: notifier()->next(node)) { alpar@877: nodes.push_back(node); alpar@877: } alpar@877: for (int i = nodes.size() - 1; i >= 0; --i) { alpar@877: snapshot.addNode(nodes[i]); alpar@877: } alpar@877: } alpar@877: virtual void clear() { alpar@877: Node node; alpar@877: for (notifier()->first(node); node != INVALID; alpar@877: notifier()->next(node)) { alpar@877: snapshot.eraseNode(node); alpar@877: } alpar@877: } alpar@877: alpar@877: Snapshot& snapshot; alpar@877: }; alpar@877: alpar@877: class EdgeObserverProxy : public EdgeNotifier::ObserverBase { alpar@877: public: alpar@877: alpar@877: EdgeObserverProxy(Snapshot& _snapshot) alpar@877: : snapshot(_snapshot) {} alpar@877: alpar@877: using EdgeNotifier::ObserverBase::attach; alpar@877: using EdgeNotifier::ObserverBase::detach; alpar@877: using EdgeNotifier::ObserverBase::attached; alpar@877: alpar@877: protected: alpar@877: alpar@877: virtual void add(const Edge& edge) { alpar@877: snapshot.addEdge(edge); alpar@877: } alpar@877: virtual void add(const std::vector& edges) { alpar@1148: for (int i = edges.size() - 1; i >= 0; --i) { alpar@877: snapshot.addEdge(edges[i]); alpar@877: } alpar@877: } alpar@877: virtual void erase(const Edge& edge) { alpar@877: snapshot.eraseEdge(edge); alpar@877: } alpar@877: virtual void erase(const std::vector& edges) { alpar@877: for (int i = 0; i < int(edges.size()); ++i) { alpar@877: snapshot.eraseEdge(edges[i]); alpar@877: } alpar@877: } alpar@877: virtual void build() { alpar@877: Edge edge; alpar@877: std::vector edges; alpar@877: for (notifier()->first(edge); edge != INVALID; alpar@877: notifier()->next(edge)) { alpar@877: edges.push_back(edge); alpar@877: } alpar@877: for (int i = edges.size() - 1; i >= 0; --i) { alpar@877: snapshot.addEdge(edges[i]); alpar@877: } alpar@877: } alpar@877: virtual void clear() { alpar@877: Edge edge; alpar@877: for (notifier()->first(edge); edge != INVALID; alpar@877: notifier()->next(edge)) { alpar@877: snapshot.eraseEdge(edge); alpar@877: } alpar@877: } alpar@877: alpar@877: Snapshot& snapshot; alpar@877: }; alpar@877: deba@1021: ListBpGraph *graph; deba@1021: deba@1021: NodeObserverProxy node_observer_proxy; deba@1021: EdgeObserverProxy edge_observer_proxy; deba@1021: deba@1021: std::list added_nodes; deba@1021: std::list added_edges; deba@1021: deba@1021: deba@1021: void addNode(const Node& node) { deba@1021: added_nodes.push_front(node); deba@1021: } deba@1021: void eraseNode(const Node& node) { deba@1021: std::list::iterator it = deba@1021: std::find(added_nodes.begin(), added_nodes.end(), node); deba@1021: if (it == added_nodes.end()) { deba@1021: clear(); deba@1021: edge_observer_proxy.detach(); deba@1021: throw NodeNotifier::ImmediateDetach(); deba@1021: } else { deba@1021: added_nodes.erase(it); deba@1021: } deba@1021: } deba@1021: deba@1021: void addEdge(const Edge& edge) { deba@1021: added_edges.push_front(edge); deba@1021: } deba@1021: void eraseEdge(const Edge& edge) { deba@1021: std::list::iterator it = deba@1021: std::find(added_edges.begin(), added_edges.end(), edge); deba@1021: if (it == added_edges.end()) { deba@1021: clear(); deba@1021: node_observer_proxy.detach(); deba@1021: throw EdgeNotifier::ImmediateDetach(); deba@1021: } else { deba@1021: added_edges.erase(it); deba@1021: } deba@1021: } deba@1021: deba@1021: void attach(ListBpGraph &_graph) { deba@1021: graph = &_graph; deba@1021: node_observer_proxy.attach(graph->notifier(Node())); deba@1021: edge_observer_proxy.attach(graph->notifier(Edge())); deba@1021: } deba@1021: deba@1021: void detach() { deba@1021: node_observer_proxy.detach(); deba@1021: edge_observer_proxy.detach(); deba@1021: } deba@1021: deba@1021: bool attached() const { deba@1021: return node_observer_proxy.attached(); deba@1021: } deba@1021: deba@1021: void clear() { deba@1021: added_nodes.clear(); deba@1021: added_edges.clear(); deba@1021: } deba@1021: deba@1021: public: deba@1021: deba@1021: /// \brief Default constructor. deba@1021: /// deba@1021: /// Default constructor. deba@1021: /// You have to call save() to actually make a snapshot. deba@1021: Snapshot() deba@1021: : graph(0), node_observer_proxy(*this), deba@1021: edge_observer_proxy(*this) {} deba@1021: deba@1021: /// \brief Constructor that immediately makes a snapshot. deba@1021: /// deba@1021: /// This constructor immediately makes a snapshot of the given graph. deba@1021: Snapshot(ListBpGraph &gr) deba@1021: : node_observer_proxy(*this), deba@1021: edge_observer_proxy(*this) { deba@1021: attach(gr); deba@1021: } deba@1021: deba@1021: /// \brief Make a snapshot. deba@1021: /// deba@1021: /// This function makes a snapshot of the given graph. deba@1021: /// It can be called more than once. In case of a repeated deba@1021: /// call, the previous snapshot gets lost. deba@1021: void save(ListBpGraph &gr) { deba@1021: if (attached()) { deba@1021: detach(); deba@1021: clear(); deba@1021: } deba@1021: attach(gr); deba@1021: } deba@1021: deba@1021: /// \brief Undo the changes until the last snapshot. deba@1021: /// deba@1021: /// This function undos the changes until the last snapshot deba@1021: /// created by save() or Snapshot(ListBpGraph&). deba@1021: /// deba@1021: /// \warning This method invalidates the snapshot, i.e. repeated deba@1021: /// restoring is not supported unless you call save() again. deba@1021: void restore() { deba@1021: detach(); deba@1021: for(std::list::iterator it = added_edges.begin(); deba@1021: it != added_edges.end(); ++it) { deba@1021: graph->erase(*it); deba@1021: } deba@1021: for(std::list::iterator it = added_nodes.begin(); deba@1021: it != added_nodes.end(); ++it) { deba@1021: graph->erase(*it); deba@1021: } deba@1021: clear(); deba@1021: } deba@1021: deba@1021: /// \brief Returns \c true if the snapshot is valid. deba@1021: /// deba@1021: /// This function returns \c true if the snapshot is valid. deba@1021: bool valid() const { deba@1021: return attached(); deba@1021: } deba@1021: }; deba@1021: }; deba@1021: deba@1021: /// @} deba@57: } //namespace lemon alpar@209: deba@57: deba@57: #endif