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@956: * Copyright (C) 2003-2010 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@782: ///\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@785: class ListDigraph; kpeter@785: 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: deba@57: std::vector nodes; deba@57: deba@57: int first_node; deba@57: deba@57: int first_free_node; deba@57: deba@57: 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@785: 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@785: 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() deba@57: : nodes(), first_node(-1), alpar@209: first_free_node(-1), arcs(), first_free_arc(-1) {} deba@57: alpar@209: alpar@209: int maxNodeId() const { return nodes.size()-1; } deba@57: int maxArcId() const { return arcs.size()-1; } deba@57: deba@57: Node source(Arc e) const { return Node(arcs[e.id].source); } deba@57: 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 { deba@57: 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; kpeter@786: n != -1 && nodes[n].first_out == -1; alpar@209: n = nodes[n].next) {} kpeter@786: arc.id = (n == -1) ? -1 : nodes[n].first_out; deba@57: } deba@57: deba@57: void next(Arc& arc) const { kpeter@786: if (arcs[arc.id].next_out != -1) { kpeter@786: arc.id = arcs[arc.id].next_out; deba@57: } else { alpar@209: int n; kpeter@786: for(n = nodes[arcs[arc.id].source].next; kpeter@786: n != -1 && nodes[n].first_out == -1; alpar@209: n = nodes[n].next) {} kpeter@786: 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 { deba@57: e.id = nodes[v.id].first_out; deba@57: } deba@57: void nextOut(Arc &e) const { deba@57: e.id=arcs[e.id].next_out; deba@57: } deba@57: deba@57: void firstIn(Arc &e, const Node& v) const { deba@57: e.id = nodes[v.id].first_in; deba@57: } deba@57: void nextIn(Arc &e) const { deba@57: 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 { alpar@209: return n.id >= 0 && n.id < static_cast(nodes.size()) && alpar@209: nodes[n.id].prev != -2; deba@149: } deba@149: alpar@209: bool valid(Arc a) const { alpar@209: return a.id >= 0 && a.id < static_cast(arcs.size()) && alpar@209: 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) { alpar@209: n = nodes.size(); alpar@209: nodes.push_back(NodeT()); deba@57: } else { alpar@209: n = first_free_node; alpar@209: first_free_node = nodes[n].next; deba@57: } alpar@209: deba@57: nodes[n].next = first_node; deba@57: if(first_node != -1) nodes[first_node].prev = n; deba@57: first_node = n; deba@57: nodes[n].prev = -1; alpar@209: deba@57: 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) { alpar@209: n = arcs.size(); alpar@209: arcs.push_back(ArcT()); deba@57: } else { alpar@209: n = first_free_arc; alpar@209: first_free_arc = arcs[n].next_in; deba@57: } alpar@209: alpar@209: arcs[n].source = u.id; deba@57: arcs[n].target = v.id; deba@57: deba@57: arcs[n].next_out = nodes[u.id].first_out; deba@57: if(nodes[u.id].first_out != -1) { alpar@209: arcs[nodes[u.id].first_out].prev_out = n; deba@57: } alpar@209: deba@57: arcs[n].next_in = nodes[v.id].first_in; deba@57: if(nodes[v.id].first_in != -1) { alpar@209: arcs[nodes[v.id].first_in].prev_in = n; deba@57: } alpar@209: deba@57: arcs[n].prev_in = arcs[n].prev_out = -1; alpar@209: deba@57: 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: deba@57: if(nodes[n].next != -1) { alpar@209: nodes[nodes[n].next].prev = nodes[n].prev; deba@57: } alpar@209: deba@57: if(nodes[n].prev != -1) { alpar@209: nodes[nodes[n].prev].next = nodes[n].next; deba@57: } else { alpar@209: first_node = nodes[n].next; deba@57: } alpar@209: deba@57: nodes[n].next = first_free_node; deba@57: first_free_node = n; deba@149: 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: deba@57: if(arcs[n].next_in!=-1) { alpar@209: arcs[arcs[n].next_in].prev_in = arcs[n].prev_in; deba@57: } deba@57: deba@57: if(arcs[n].prev_in!=-1) { alpar@209: arcs[arcs[n].prev_in].next_in = arcs[n].next_in; deba@57: } else { alpar@209: nodes[arcs[n].target].first_in = arcs[n].next_in; deba@57: } deba@57: alpar@209: deba@57: if(arcs[n].next_out!=-1) { alpar@209: arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; alpar@209: } deba@57: deba@57: if(arcs[n].prev_out!=-1) { alpar@209: arcs[arcs[n].prev_out].next_out = arcs[n].next_out; deba@57: } else { alpar@209: nodes[arcs[n].source].first_out = arcs[n].next_out; deba@57: } alpar@209: deba@57: arcs[n].next_in = first_free_arc; deba@149: first_free_arc = n; deba@149: arcs[n].prev_in = -2; deba@57: } deba@57: deba@57: void clear() { deba@57: arcs.clear(); deba@57: 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: { deba@57: if(arcs[e.id].next_in != -1) alpar@209: arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in; deba@57: if(arcs[e.id].prev_in != -1) alpar@209: arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in; deba@57: else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in; deba@57: if (nodes[n.id].first_in != -1) { alpar@209: arcs[nodes[n.id].first_in].prev_in = e.id; deba@57: } deba@57: arcs[e.id].target = n.id; deba@57: arcs[e.id].prev_in = -1; deba@57: arcs[e.id].next_in = nodes[n.id].first_in; deba@57: nodes[n.id].first_in = e.id; deba@57: } alpar@209: void changeSource(Arc e, Node n) deba@57: { deba@57: if(arcs[e.id].next_out != -1) alpar@209: arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out; deba@57: if(arcs[e.id].prev_out != -1) alpar@209: arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out; deba@57: else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out; deba@57: if (nodes[n.id].first_out != -1) { alpar@209: arcs[nodes[n.id].first_out].prev_out = e.id; deba@57: } deba@57: arcs[e.id].source = n.id; deba@57: arcs[e.id].prev_out = -1; deba@57: arcs[e.id].next_out = nodes[n.id].first_out; deba@57: 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@782: ///\ref ListDigraph is a versatile and fast directed graph kpeter@782: ///implementation based on linked lists that are stored in alpar@209: ///\c std::vector structures. deba@57: /// kpeter@782: ///This type fully conforms to the \ref concepts::Digraph "Digraph concept" kpeter@782: ///and it also provides several useful additional functionalities. kpeter@782: ///Most of its member functions and nested classes are documented kpeter@73: ///only in the concept class. deba@57: /// kpeter@834: ///This class provides only linear time counting for nodes and arcs. kpeter@834: /// kpeter@73: ///\sa concepts::Digraph kpeter@782: ///\sa ListGraph deba@57: class ListDigraph : public ExtendedListDigraphBase { kpeter@664: typedef ExtendedListDigraphBase Parent; kpeter@664: deba@57: private: kpeter@782: /// Digraphs are \e not copy constructible. Use DigraphCopy instead. deba@57: ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {}; kpeter@782: /// \brief Assignment of a digraph to another one is \e not allowed. kpeter@782: /// 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@782: ///This function adds a new node to the digraph. kpeter@606: ///\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@782: ///This function adds a new arc to the digraph with source node \c s deba@57: ///and target node \c t. kpeter@606: ///\return The new arc. kpeter@782: 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@834: ///This function erases the given node along with its outgoing and kpeter@834: ///incoming arcs from the digraph. kpeter@834: /// kpeter@834: ///\note All iterators referencing the removed node or the connected kpeter@834: ///arcs are invalidated, of course. kpeter@782: void erase(Node n) { Parent::erase(n); } deba@234: deba@234: ///\brief Erase an arc from the digraph. deba@234: /// kpeter@782: ///This function erases the given arc from the digraph. kpeter@834: /// kpeter@834: ///\note All iterators referencing the removed arc are invalidated, kpeter@834: ///of course. kpeter@782: void erase(Arc a) { Parent::erase(a); } deba@234: deba@149: /// Node validity check deba@149: kpeter@782: /// This function gives back \c true if the given node is valid, kpeter@782: /// i.e. it is a real node of the digraph. deba@149: /// kpeter@782: /// \warning A removed node could become valid again if new nodes are kpeter@782: /// 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@782: /// This function gives back \c true if the given arc is valid, kpeter@782: /// i.e. it is a real arc of the digraph. deba@149: /// kpeter@782: /// \warning A removed arc could become valid again if new arcs are kpeter@782: /// added to the digraph. deba@149: bool valid(Arc a) const { return Parent::valid(a); } deba@149: kpeter@782: /// Change the target node of an arc deba@57: kpeter@782: /// This function changes the target node of the given arc \c a to \c n. deba@57: /// kpeter@782: ///\note \c ArcIt and \c OutArcIt iterators referencing the changed kpeter@833: ///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@782: /// Change the source node of an arc deba@57: kpeter@782: /// This function changes the source node of the given arc \c a to \c n. deba@57: /// kpeter@782: ///\note \c InArcIt iterators referencing the changed arc remain kpeter@833: ///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@782: /// Reverse the direction of an arc. deba@57: kpeter@782: /// This function reverses the direction of the given arc. kpeter@782: ///\note \c ArcIt, \c OutArcIt and \c InArcIt iterators referencing kpeter@782: ///the changed arc are invalidated. kpeter@73: /// deba@57: ///\warning This functionality cannot be used together with the Snapshot deba@57: ///feature. kpeter@782: void reverseArc(Arc a) { kpeter@782: Node t=target(a); kpeter@782: changeTarget(a,source(a)); kpeter@782: changeSource(a,t); deba@57: } deba@57: deba@57: ///Contract two nodes. deba@57: kpeter@782: ///This function contracts the given two nodes. kpeter@782: ///Node \c v is removed, but instead of deleting its kpeter@782: ///incident arcs, they are joined to node \c u. kpeter@782: ///If the last parameter \c r is \c true (this is the default value), kpeter@782: ///then the newly created loops are removed. deba@57: /// kpeter@782: ///\note The moved arcs are joined to node \c u using changeSource() kpeter@782: ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are kpeter@782: ///invalidated for the outgoing arcs of node \c v and \c InArcIt kpeter@782: ///iterators are invalidated for the incomming arcs of \c v. alpar@956: ///Moreover all iterators referencing node \c v or the removed kpeter@782: ///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@782: void contract(Node u, Node v, bool r = true) deba@57: { kpeter@782: for(OutArcIt e(*this,v);e!=INVALID;) { alpar@209: OutArcIt f=e; alpar@209: ++f; kpeter@782: if(r && target(e)==u) erase(e); kpeter@782: else changeSource(e,u); alpar@209: e=f; deba@57: } kpeter@782: for(InArcIt e(*this,v);e!=INVALID;) { alpar@209: InArcIt f=e; alpar@209: ++f; kpeter@782: if(r && source(e)==u) erase(e); kpeter@782: else changeTarget(e,u); alpar@209: e=f; deba@57: } kpeter@782: erase(v); deba@57: } deba@57: deba@57: ///Split a node. deba@57: kpeter@782: ///This function splits the given node. First, a new node is added kpeter@782: ///to the digraph, then the source of each outgoing arc of node \c n kpeter@782: ///is moved to this new node. kpeter@782: ///If the second parameter \c connect is \c true (this is the default kpeter@782: ///value), then a new arc from node \c n to the newly created node kpeter@782: ///is also added. deba@57: ///\return The newly created node. deba@57: /// kpeter@785: ///\note All iterators remain valid. deba@57: /// kpeter@782: ///\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(); kpeter@785: nodes[b.id].first_out=nodes[n.id].first_out; kpeter@785: nodes[n.id].first_out=-1; kpeter@785: for(int i=nodes[b.id].first_out; i!=-1; i=arcs[i].next_out) { kpeter@785: 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@782: ///This function splits the given arc. First, a new node \c v is kpeter@782: ///added to the digraph, then the target node of the original arc kpeter@782: ///is set to \c v. Finally, an arc from \c v to the original target kpeter@782: ///is added. kpeter@782: ///\return The newly created node. kpeter@73: /// kpeter@782: ///\note \c InArcIt iterators referencing the original arc are kpeter@782: ///invalidated. Other iterators remain valid. kpeter@73: /// kpeter@73: ///\warning This functionality cannot be used together with the kpeter@73: ///Snapshot feature. kpeter@782: Node split(Arc a) { kpeter@782: Node v = addNode(); kpeter@782: addArc(v,target(a)); kpeter@782: changeTarget(a,v); kpeter@782: return v; deba@57: } alpar@209: kpeter@782: ///Clear the digraph. kpeter@782: kpeter@782: ///This function erases all nodes and arcs from the digraph. kpeter@782: /// kpeter@834: ///\note All iterators of the digraph are invalidated, of course. kpeter@782: void clear() { kpeter@782: Parent::clear(); kpeter@782: } kpeter@782: kpeter@782: /// Reserve memory for nodes. kpeter@782: kpeter@782: /// Using this function, it is possible to avoid superfluous memory kpeter@782: /// allocation: if you know that the digraph you want to build will kpeter@782: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@782: /// then it is worth reserving space for this amount before starting kpeter@782: /// to build the digraph. kpeter@782: /// \sa reserveArc() kpeter@782: void reserveNode(int n) { nodes.reserve(n); }; kpeter@782: kpeter@782: /// Reserve memory for arcs. kpeter@782: kpeter@782: /// Using this function, it is possible to avoid superfluous memory kpeter@782: /// allocation: if you know that the digraph you want to build will kpeter@782: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@782: /// then it is worth reserving space for this amount before starting kpeter@782: /// to build the digraph. kpeter@782: /// \sa reserveNode() kpeter@782: void reserveArc(int m) { arcs.reserve(m); }; kpeter@782: 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@956: /// \note After a state is restored, you cannot restore a later state, kpeter@782: /// i.e. you cannot add the removed nodes and arcs again using kpeter@782: /// another Snapshot instance. kpeter@782: /// kpeter@782: /// \warning Node and arc deletions and other modifications (e.g. kpeter@782: /// reversing, contracting, splitting arcs or nodes) cannot be alpar@209: /// restored. These events invalidate the snapshot. kpeter@833: /// However, the arcs and nodes that were added to the digraph after kpeter@782: /// 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) { 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 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) { 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 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@782: /// 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@782: /// This constructor immediately makes a snapshot of the given digraph. kpeter@782: Snapshot(ListDigraph &gr) alpar@209: : node_observer_proxy(*this), deba@57: arc_observer_proxy(*this) { kpeter@782: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Make a snapshot. deba@57: /// kpeter@782: /// This function makes a snapshot of the given digraph. kpeter@782: /// It can be called more than once. In case of a repeated deba@57: /// call, the previous snapshot gets lost. kpeter@782: void save(ListDigraph &gr) { deba@57: if (attached()) { deba@57: detach(); deba@57: clear(); deba@57: } kpeter@782: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Undo the changes until the last snapshot. kpeter@782: /// kpeter@782: /// This function undos the changes until the last snapshot kpeter@782: /// created by save() or Snapshot(ListDigraph&). kpeter@787: /// kpeter@787: /// \warning This method invalidates the snapshot, i.e. repeated kpeter@787: /// 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@782: /// \brief Returns \c true if the snapshot is valid. deba@57: /// kpeter@782: /// 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: deba@57: std::vector nodes; deba@57: deba@57: int first_node; deba@57: deba@57: int first_free_node; deba@57: deba@57: std::vector arcs; deba@57: deba@57: int first_free_arc; alpar@209: deba@57: public: alpar@209: kpeter@664: 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@341: operator Edge() const { kpeter@341: 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() deba@57: : nodes(), first_node(-1), alpar@209: first_free_node(-1), arcs(), first_free_arc(-1) {} deba@57: alpar@209: alpar@209: int maxNodeId() const { return nodes.size()-1; } deba@57: int maxEdgeId() const { return arcs.size() / 2 - 1; } deba@57: int maxArcId() const { return arcs.size()-1; } deba@57: deba@57: Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); } deba@57: Node target(Arc e) const { return Node(arcs[e.id].target); } deba@57: deba@57: Node u(Edge e) const { return Node(arcs[2 * e.id].target); } deba@57: 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 { deba@57: node.id = nodes[node.id].next; deba@57: } deba@57: alpar@209: void first(Arc& e) const { deba@57: int n = first_node; deba@57: while (n != -1 && nodes[n].first_out == -1) { deba@57: n = nodes[n].next; deba@57: } deba@57: e.id = (n == -1) ? -1 : nodes[n].first_out; deba@57: } deba@57: deba@57: void next(Arc& e) const { deba@57: if (arcs[e.id].next_out != -1) { alpar@209: e.id = arcs[e.id].next_out; deba@57: } else { alpar@209: int n = nodes[arcs[e.id ^ 1].target].next; deba@57: while(n != -1 && nodes[n].first_out == -1) { deba@57: n = nodes[n].next; deba@57: } alpar@209: 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) { deba@57: e.id = nodes[n].first_out; deba@57: while ((e.id & 1) != 1) { deba@57: 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: } deba@57: n = nodes[n].next; deba@57: } deba@57: e.id = -1; deba@57: } deba@57: deba@57: void next(Edge& e) const { deba@57: int n = arcs[e.id * 2].target; deba@57: e.id = arcs[(e.id * 2) | 1].next_out; deba@57: while ((e.id & 1) != 1) { deba@57: 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: } deba@57: n = nodes[n].next; deba@57: while (n != -1) { deba@57: e.id = nodes[n].first_out; deba@57: while ((e.id & 1) != 1) { deba@57: 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: } deba@57: 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 { deba@57: e.id = nodes[v.id].first_out; deba@57: } deba@57: void nextOut(Arc &e) const { deba@57: e.id = arcs[e.id].next_out; deba@57: } deba@57: deba@57: void firstIn(Arc &e, const Node& v) const { deba@57: 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 { deba@57: 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 { kpeter@73: 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 { kpeter@73: 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 { alpar@209: return n.id >= 0 && n.id < static_cast(nodes.size()) && alpar@209: nodes[n.id].prev != -2; deba@149: } deba@149: alpar@209: bool valid(Arc a) const { alpar@209: return a.id >= 0 && a.id < static_cast(arcs.size()) && alpar@209: arcs[a.id].prev_out != -2; deba@149: } deba@149: alpar@209: bool valid(Edge e) const { alpar@209: return e.id >= 0 && 2 * e.id < static_cast(arcs.size()) && alpar@209: 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) { alpar@209: n = nodes.size(); alpar@209: nodes.push_back(NodeT()); deba@57: } else { alpar@209: n = first_free_node; alpar@209: first_free_node = nodes[n].next; deba@57: } alpar@209: deba@57: nodes[n].next = first_node; deba@57: if (first_node != -1) nodes[first_node].prev = n; deba@57: first_node = n; deba@57: nodes[n].prev = -1; alpar@209: deba@57: 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) { alpar@209: n = arcs.size(); alpar@209: arcs.push_back(ArcT()); alpar@209: arcs.push_back(ArcT()); deba@57: } else { alpar@209: n = first_free_arc; alpar@209: first_free_arc = arcs[n].next_out; deba@57: } alpar@209: deba@57: arcs[n].target = u.id; deba@57: arcs[n | 1].target = v.id; deba@57: deba@57: arcs[n].next_out = nodes[v.id].first_out; deba@57: if (nodes[v.id].first_out != -1) { alpar@209: arcs[nodes[v.id].first_out].prev_out = n; alpar@209: } deba@57: arcs[n].prev_out = -1; deba@57: nodes[v.id].first_out = n; alpar@209: deba@57: arcs[n | 1].next_out = nodes[u.id].first_out; deba@57: if (nodes[u.id].first_out != -1) { alpar@209: arcs[nodes[u.id].first_out].prev_out = (n | 1); deba@57: } alpar@209: arcs[n | 1].prev_out = -1; deba@57: 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: deba@57: if(nodes[n].next != -1) { alpar@209: nodes[nodes[n].next].prev = nodes[n].prev; deba@57: } alpar@209: deba@57: if(nodes[n].prev != -1) { alpar@209: nodes[nodes[n].prev].next = nodes[n].next; deba@57: } else { alpar@209: first_node = nodes[n].next; deba@57: } alpar@209: deba@57: nodes[n].next = first_free_node; deba@57: first_free_node = n; deba@149: nodes[n].prev = -2; deba@57: } alpar@209: kpeter@73: void erase(const Edge& edge) { kpeter@73: int n = edge.id * 2; alpar@209: deba@57: if (arcs[n].next_out != -1) { alpar@209: arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; alpar@209: } deba@57: deba@57: if (arcs[n].prev_out != -1) { alpar@209: arcs[arcs[n].prev_out].next_out = arcs[n].next_out; deba@57: } else { alpar@209: nodes[arcs[n | 1].target].first_out = arcs[n].next_out; deba@57: } deba@57: deba@57: if (arcs[n | 1].next_out != -1) { alpar@209: arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out; alpar@209: } deba@57: deba@57: if (arcs[n | 1].prev_out != -1) { alpar@209: arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out; deba@57: } else { alpar@209: nodes[arcs[n].target].first_out = arcs[n | 1].next_out; deba@57: } alpar@209: deba@57: arcs[n].next_out = first_free_arc; alpar@209: first_free_arc = n; deba@149: arcs[n].prev_out = -2; deba@149: arcs[n | 1].prev_out = -2; deba@57: deba@57: } deba@57: deba@57: void clear() { deba@57: arcs.clear(); deba@57: 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) { deba@57: if(arcs[2 * e.id].next_out != -1) { alpar@209: arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out; deba@57: } deba@57: if(arcs[2 * e.id].prev_out != -1) { alpar@209: arcs[arcs[2 * e.id].prev_out].next_out = deba@57: arcs[2 * e.id].next_out; deba@57: } else { alpar@209: nodes[arcs[(2 * e.id) | 1].target].first_out = deba@57: arcs[2 * e.id].next_out; deba@57: } deba@57: deba@57: if (nodes[n.id].first_out != -1) { alpar@209: arcs[nodes[n.id].first_out].prev_out = 2 * e.id; deba@57: } deba@57: arcs[(2 * e.id) | 1].target = n.id; deba@57: arcs[2 * e.id].prev_out = -1; deba@57: arcs[2 * e.id].next_out = nodes[n.id].first_out; deba@57: nodes[n.id].first_out = 2 * e.id; deba@57: } deba@57: deba@235: void changeU(Edge e, Node n) { deba@57: if(arcs[(2 * e.id) | 1].next_out != -1) { alpar@209: arcs[arcs[(2 * e.id) | 1].next_out].prev_out = deba@57: arcs[(2 * e.id) | 1].prev_out; deba@57: } deba@57: if(arcs[(2 * e.id) | 1].prev_out != -1) { alpar@209: arcs[arcs[(2 * e.id) | 1].prev_out].next_out = deba@57: arcs[(2 * e.id) | 1].next_out; deba@57: } else { alpar@209: nodes[arcs[2 * e.id].target].first_out = deba@57: arcs[(2 * e.id) | 1].next_out; deba@57: } deba@57: deba@57: if (nodes[n.id].first_out != -1) { alpar@209: arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); deba@57: } deba@57: arcs[2 * e.id].target = n.id; deba@57: arcs[(2 * e.id) | 1].prev_out = -1; deba@57: arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out; deba@57: 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@782: ///\ref ListGraph is a versatile and fast undirected graph kpeter@782: ///implementation based on linked lists that are stored in alpar@209: ///\c std::vector structures. deba@57: /// kpeter@782: ///This type fully conforms to the \ref concepts::Graph "Graph concept" kpeter@782: ///and it also provides several useful additional functionalities. kpeter@782: ///Most of its member functions and nested classes are documented kpeter@73: ///only in the concept class. kpeter@73: /// kpeter@834: ///This class provides only linear time counting for nodes, edges and arcs. kpeter@834: /// kpeter@73: ///\sa concepts::Graph kpeter@782: ///\sa ListDigraph deba@57: class ListGraph : public ExtendedListGraphBase { kpeter@664: typedef ExtendedListGraphBase Parent; kpeter@664: deba@57: private: kpeter@782: /// Graphs are \e not copy constructible. Use GraphCopy instead. deba@57: ListGraph(const ListGraph &) :ExtendedListGraphBase() {}; kpeter@782: /// \brief Assignment of a graph to another one is \e not allowed. kpeter@782: /// 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: kpeter@73: typedef Parent::OutArcIt IncEdgeIt; deba@57: kpeter@73: /// \brief Add a new node to the graph. deba@57: /// kpeter@782: /// This function adds a new node to the graph. kpeter@606: /// \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@782: /// This function adds a new edge to the graph between nodes kpeter@782: /// \c u and \c v with inherent orientation from node \c u to kpeter@782: /// node \c v. kpeter@606: /// \return The new edge. kpeter@782: Edge addEdge(Node u, Node v) { kpeter@782: return Parent::addEdge(u, v); deba@57: } deba@234: kpeter@782: ///\brief Erase a node from the graph. deba@234: /// kpeter@834: /// This function erases the given node along with its incident arcs kpeter@834: /// from the graph. kpeter@834: /// kpeter@834: /// \note All iterators referencing the removed node or the incident kpeter@834: /// edges are invalidated, of course. kpeter@782: void erase(Node n) { Parent::erase(n); } kpeter@782: kpeter@782: ///\brief Erase an edge from the graph. deba@234: /// kpeter@782: /// This function erases the given edge from the graph. kpeter@834: /// kpeter@834: /// \note All iterators referencing the removed edge are invalidated, kpeter@834: /// of course. kpeter@782: void erase(Edge e) { Parent::erase(e); } deba@149: /// Node validity check deba@149: kpeter@782: /// This function gives back \c true if the given node is valid, kpeter@782: /// i.e. it is a real node of the graph. deba@149: /// kpeter@782: /// \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@782: /// Edge validity check kpeter@782: kpeter@782: /// This function gives back \c true if the given edge is valid, kpeter@782: /// i.e. it is a real edge of the graph. kpeter@782: /// kpeter@782: /// \warning A removed edge could become valid again if new edges are kpeter@782: /// added to the graph. kpeter@782: bool valid(Edge e) const { return Parent::valid(e); } deba@149: /// Arc validity check deba@149: kpeter@782: /// This function gives back \c true if the given arc is valid, kpeter@782: /// i.e. it is a real arc of the graph. deba@149: /// kpeter@782: /// \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@782: /// \brief Change the first node of an edge. deba@149: /// kpeter@782: /// This function changes the first node of the given edge \c e to \c n. deba@57: /// kpeter@782: ///\note \c EdgeIt and \c ArcIt iterators referencing the kpeter@782: ///changed edge are invalidated and all other iterators whose kpeter@782: ///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@782: /// \brief Change the second node of an edge. deba@57: /// kpeter@782: /// This function changes the second node of the given edge \c e to \c n. deba@57: /// kpeter@782: ///\note \c EdgeIt iterators referencing the changed edge remain kpeter@833: ///valid, but \c ArcIt iterators referencing the changed edge and kpeter@782: ///all other iterators whose base node is the changed node are also kpeter@782: ///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@782: deba@57: /// \brief Contract two nodes. deba@57: /// kpeter@782: /// This function contracts the given two nodes. kpeter@782: /// Node \c b is removed, but instead of deleting kpeter@782: /// its incident edges, they are joined to node \c a. kpeter@782: /// If the last parameter \c r is \c true (this is the default value), kpeter@782: /// then the newly created loops are removed. deba@57: /// kpeter@782: /// \note The moved edges are joined to node \c a using changeU() kpeter@782: /// or changeV(), thus all edge and arc iterators whose base node is kpeter@782: /// \c b are invalidated. alpar@956: /// Moreover all iterators referencing node \c b or the removed kpeter@782: /// 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@782: ///Clear the graph. kpeter@782: kpeter@782: ///This function erases all nodes and arcs from the graph. kpeter@782: /// kpeter@834: ///\note All iterators of the graph are invalidated, of course. kpeter@782: void clear() { kpeter@782: Parent::clear(); kpeter@782: } kpeter@664: kpeter@783: /// Reserve memory for nodes. kpeter@783: kpeter@783: /// Using this function, it is possible to avoid superfluous memory kpeter@783: /// allocation: if you know that the graph you want to build will kpeter@783: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@783: /// then it is worth reserving space for this amount before starting kpeter@783: /// to build the graph. kpeter@783: /// \sa reserveEdge() kpeter@783: void reserveNode(int n) { nodes.reserve(n); }; kpeter@783: kpeter@783: /// Reserve memory for edges. kpeter@783: kpeter@783: /// Using this function, it is possible to avoid superfluous memory kpeter@783: /// allocation: if you know that the graph you want to build will kpeter@783: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@783: /// then it is worth reserving space for this amount before starting kpeter@783: /// to build the graph. kpeter@783: /// \sa reserveNode() kpeter@783: 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@956: /// \note After a state is restored, you cannot restore a later state, kpeter@782: /// i.e. you cannot add the removed nodes and edges again using kpeter@782: /// another Snapshot instance. kpeter@782: /// kpeter@782: /// \warning Node and edge deletions and other modifications kpeter@782: /// (e.g. changing the end-nodes of edges or contracting nodes) kpeter@782: /// cannot be restored. These events invalidate the snapshot. kpeter@833: /// However, the edges and nodes that were added to the graph after kpeter@782: /// 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) { 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 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) { kpeter@73: 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@782: /// 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@782: /// This constructor immediately makes a snapshot of the given graph. kpeter@782: Snapshot(ListGraph &gr) alpar@209: : node_observer_proxy(*this), kpeter@73: edge_observer_proxy(*this) { kpeter@782: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Make a snapshot. deba@57: /// kpeter@782: /// This function makes a snapshot of the given graph. kpeter@782: /// It can be called more than once. In case of a repeated deba@57: /// call, the previous snapshot gets lost. kpeter@782: void save(ListGraph &gr) { deba@57: if (attached()) { deba@57: detach(); deba@57: clear(); deba@57: } kpeter@782: attach(gr); deba@57: } alpar@209: deba@57: /// \brief Undo the changes until the last snapshot. kpeter@782: /// kpeter@782: /// This function undos the changes until the last snapshot kpeter@782: /// created by save() or Snapshot(ListGraph&). kpeter@787: /// kpeter@787: /// \warning This method invalidates the snapshot, i.e. repeated kpeter@787: /// 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@782: /// \brief Returns \c true if the snapshot is valid. deba@57: /// kpeter@782: /// 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: /// @} deba@57: } //namespace lemon alpar@209: deba@57: deba@57: #endif