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@1270: * 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@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@1217: ///iterators are invalidated for the incoming 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) { alpar@1355: 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@1355: 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) { alpar@1355: 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@1355: 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: /// @} alpar@1356: alpar@1356: class ListBpGraphBase { alpar@1356: alpar@1356: protected: alpar@1356: alpar@1356: struct NodeT { alpar@1356: int first_out; alpar@1356: int prev, next; alpar@1356: int partition_prev, partition_next; alpar@1356: int partition_index; alpar@1356: bool red; alpar@1356: }; alpar@1356: alpar@1356: struct ArcT { alpar@1356: int target; alpar@1356: int prev_out, next_out; alpar@1356: }; alpar@1356: alpar@1356: std::vector nodes; alpar@1356: alpar@1356: int first_node, first_red, first_blue; alpar@1356: int max_red, max_blue; alpar@1356: alpar@1356: int first_free_red, first_free_blue; alpar@1356: alpar@1356: std::vector arcs; alpar@1356: alpar@1356: int first_free_arc; alpar@1356: alpar@1356: public: alpar@1356: alpar@1356: typedef ListBpGraphBase BpGraph; alpar@1356: alpar@1356: class Node { alpar@1356: friend class ListBpGraphBase; alpar@1356: protected: alpar@1356: alpar@1356: int id; alpar@1356: explicit Node(int pid) { id = pid;} alpar@1356: alpar@1356: public: alpar@1356: Node() {} alpar@1356: Node (Invalid) { id = -1; } alpar@1356: bool operator==(const Node& node) const {return id == node.id;} alpar@1356: bool operator!=(const Node& node) const {return id != node.id;} alpar@1356: bool operator<(const Node& node) const {return id < node.id;} alpar@1356: }; alpar@1356: alpar@1356: class RedNode : public Node { alpar@1356: friend class ListBpGraphBase; alpar@1356: protected: alpar@1356: alpar@1356: explicit RedNode(int pid) : Node(pid) {} alpar@1356: alpar@1356: public: alpar@1356: RedNode() {} alpar@1356: RedNode(const RedNode& node) : Node(node) {} alpar@1356: RedNode(Invalid) : Node(INVALID){} alpar@1356: }; alpar@1356: alpar@1356: class BlueNode : public Node { alpar@1356: friend class ListBpGraphBase; alpar@1356: protected: alpar@1356: alpar@1356: explicit BlueNode(int pid) : Node(pid) {} alpar@1356: alpar@1356: public: alpar@1356: BlueNode() {} alpar@1356: BlueNode(const BlueNode& node) : Node(node) {} alpar@1356: BlueNode(Invalid) : Node(INVALID){} alpar@1356: }; alpar@1356: alpar@1356: class Edge { alpar@1356: friend class ListBpGraphBase; alpar@1356: protected: alpar@1356: alpar@1356: int id; alpar@1356: explicit Edge(int pid) { id = pid;} alpar@1356: alpar@1356: public: alpar@1356: Edge() {} alpar@1356: Edge (Invalid) { id = -1; } alpar@1356: bool operator==(const Edge& edge) const {return id == edge.id;} alpar@1356: bool operator!=(const Edge& edge) const {return id != edge.id;} alpar@1356: bool operator<(const Edge& edge) const {return id < edge.id;} alpar@1356: }; alpar@1356: alpar@1356: class Arc { alpar@1356: friend class ListBpGraphBase; alpar@1356: protected: alpar@1356: alpar@1356: int id; alpar@1356: explicit Arc(int pid) { id = pid;} alpar@1356: alpar@1356: public: alpar@1356: operator Edge() const { alpar@1356: return id != -1 ? edgeFromId(id / 2) : INVALID; alpar@1356: } alpar@1356: alpar@1356: Arc() {} alpar@1356: Arc (Invalid) { id = -1; } alpar@1356: bool operator==(const Arc& arc) const {return id == arc.id;} alpar@1356: bool operator!=(const Arc& arc) const {return id != arc.id;} alpar@1356: bool operator<(const Arc& arc) const {return id < arc.id;} alpar@1356: }; alpar@1356: alpar@1356: ListBpGraphBase() alpar@1356: : nodes(), first_node(-1), alpar@1356: first_red(-1), first_blue(-1), alpar@1356: max_red(-1), max_blue(-1), alpar@1356: first_free_red(-1), first_free_blue(-1), alpar@1356: arcs(), first_free_arc(-1) {} alpar@1356: alpar@1356: alpar@1356: bool red(Node n) const { return nodes[n.id].red; } alpar@1356: bool blue(Node n) const { return !nodes[n.id].red; } alpar@1356: alpar@1356: static RedNode asRedNodeUnsafe(Node n) { return RedNode(n.id); } alpar@1356: static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n.id); } alpar@1356: alpar@1356: int maxNodeId() const { return nodes.size()-1; } alpar@1356: int maxRedId() const { return max_red; } alpar@1356: int maxBlueId() const { return max_blue; } alpar@1356: int maxEdgeId() const { return arcs.size() / 2 - 1; } alpar@1356: int maxArcId() const { return arcs.size()-1; } alpar@1356: alpar@1356: Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); } alpar@1356: Node target(Arc e) const { return Node(arcs[e.id].target); } alpar@1356: alpar@1356: RedNode redNode(Edge e) const { alpar@1356: return RedNode(arcs[2 * e.id].target); alpar@1356: } alpar@1356: BlueNode blueNode(Edge e) const { alpar@1356: return BlueNode(arcs[2 * e.id + 1].target); alpar@1356: } alpar@1356: alpar@1356: static bool direction(Arc e) { alpar@1356: return (e.id & 1) == 1; alpar@1356: } alpar@1356: alpar@1356: static Arc direct(Edge e, bool d) { alpar@1356: return Arc(e.id * 2 + (d ? 1 : 0)); alpar@1356: } alpar@1356: alpar@1356: void first(Node& node) const { alpar@1356: node.id = first_node; alpar@1356: } alpar@1356: alpar@1356: void next(Node& node) const { alpar@1356: node.id = nodes[node.id].next; alpar@1356: } alpar@1356: alpar@1356: void first(RedNode& node) const { alpar@1356: node.id = first_red; alpar@1356: } alpar@1356: alpar@1356: void next(RedNode& node) const { alpar@1356: node.id = nodes[node.id].partition_next; alpar@1356: } alpar@1356: alpar@1356: void first(BlueNode& node) const { alpar@1356: node.id = first_blue; alpar@1356: } alpar@1356: alpar@1356: void next(BlueNode& node) const { alpar@1356: node.id = nodes[node.id].partition_next; alpar@1356: } alpar@1356: alpar@1356: void first(Arc& e) const { alpar@1356: int n = first_node; alpar@1356: while (n != -1 && nodes[n].first_out == -1) { alpar@1356: n = nodes[n].next; alpar@1356: } alpar@1356: e.id = (n == -1) ? -1 : nodes[n].first_out; alpar@1356: } alpar@1356: alpar@1356: void next(Arc& e) const { alpar@1356: if (arcs[e.id].next_out != -1) { alpar@1356: e.id = arcs[e.id].next_out; alpar@1356: } else { alpar@1356: int n = nodes[arcs[e.id ^ 1].target].next; alpar@1356: while(n != -1 && nodes[n].first_out == -1) { alpar@1356: n = nodes[n].next; alpar@1356: } alpar@1356: e.id = (n == -1) ? -1 : nodes[n].first_out; alpar@1356: } alpar@1356: } alpar@1356: alpar@1356: void first(Edge& e) const { alpar@1356: int n = first_node; alpar@1356: while (n != -1) { alpar@1356: e.id = nodes[n].first_out; alpar@1356: while ((e.id & 1) != 1) { alpar@1356: e.id = arcs[e.id].next_out; alpar@1356: } alpar@1356: if (e.id != -1) { alpar@1356: e.id /= 2; alpar@1356: return; alpar@1356: } alpar@1356: n = nodes[n].next; alpar@1356: } alpar@1356: e.id = -1; alpar@1356: } alpar@1356: alpar@1356: void next(Edge& e) const { alpar@1356: int n = arcs[e.id * 2].target; alpar@1356: e.id = arcs[(e.id * 2) | 1].next_out; alpar@1356: while ((e.id & 1) != 1) { alpar@1356: e.id = arcs[e.id].next_out; alpar@1356: } alpar@1356: if (e.id != -1) { alpar@1356: e.id /= 2; alpar@1356: return; alpar@1356: } alpar@1356: n = nodes[n].next; alpar@1356: while (n != -1) { alpar@1356: e.id = nodes[n].first_out; alpar@1356: while ((e.id & 1) != 1) { alpar@1356: e.id = arcs[e.id].next_out; alpar@1356: } alpar@1356: if (e.id != -1) { alpar@1356: e.id /= 2; alpar@1356: return; alpar@1356: } alpar@1356: n = nodes[n].next; alpar@1356: } alpar@1356: e.id = -1; alpar@1356: } alpar@1356: alpar@1356: void firstOut(Arc &e, const Node& v) const { alpar@1356: e.id = nodes[v.id].first_out; alpar@1356: } alpar@1356: void nextOut(Arc &e) const { alpar@1356: e.id = arcs[e.id].next_out; alpar@1356: } alpar@1356: alpar@1356: void firstIn(Arc &e, const Node& v) const { alpar@1356: e.id = ((nodes[v.id].first_out) ^ 1); alpar@1356: if (e.id == -2) e.id = -1; alpar@1356: } alpar@1356: void nextIn(Arc &e) const { alpar@1356: e.id = ((arcs[e.id ^ 1].next_out) ^ 1); alpar@1356: if (e.id == -2) e.id = -1; alpar@1356: } alpar@1356: alpar@1356: void firstInc(Edge &e, bool& d, const Node& v) const { alpar@1356: int a = nodes[v.id].first_out; alpar@1356: if (a != -1 ) { alpar@1356: e.id = a / 2; alpar@1356: d = ((a & 1) == 1); alpar@1356: } else { alpar@1356: e.id = -1; alpar@1356: d = true; alpar@1356: } alpar@1356: } alpar@1356: void nextInc(Edge &e, bool& d) const { alpar@1356: int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out); alpar@1356: if (a != -1 ) { alpar@1356: e.id = a / 2; alpar@1356: d = ((a & 1) == 1); alpar@1356: } else { alpar@1356: e.id = -1; alpar@1356: d = true; alpar@1356: } alpar@1356: } alpar@1356: alpar@1356: static int id(Node v) { return v.id; } alpar@1356: int id(RedNode v) const { return nodes[v.id].partition_index; } alpar@1356: int id(BlueNode v) const { return nodes[v.id].partition_index; } alpar@1356: static int id(Arc e) { return e.id; } alpar@1356: static int id(Edge e) { return e.id; } alpar@1356: alpar@1356: static Node nodeFromId(int id) { return Node(id);} alpar@1356: static Arc arcFromId(int id) { return Arc(id);} alpar@1356: static Edge edgeFromId(int id) { return Edge(id);} alpar@1356: alpar@1356: bool valid(Node n) const { alpar@1356: return n.id >= 0 && n.id < static_cast(nodes.size()) && alpar@1356: nodes[n.id].prev != -2; alpar@1356: } alpar@1356: alpar@1356: bool valid(Arc a) const { alpar@1356: return a.id >= 0 && a.id < static_cast(arcs.size()) && alpar@1356: arcs[a.id].prev_out != -2; alpar@1356: } alpar@1356: alpar@1356: bool valid(Edge e) const { alpar@1356: return e.id >= 0 && 2 * e.id < static_cast(arcs.size()) && alpar@1356: arcs[2 * e.id].prev_out != -2; alpar@1356: } alpar@1356: alpar@1356: RedNode addRedNode() { alpar@1356: int n; alpar@1356: alpar@1356: if(first_free_red==-1) { alpar@1356: n = nodes.size(); alpar@1356: nodes.push_back(NodeT()); alpar@1356: nodes[n].partition_index = ++max_red; alpar@1356: nodes[n].red = true; alpar@1356: } else { alpar@1356: n = first_free_red; alpar@1356: first_free_red = nodes[n].next; alpar@1356: } alpar@1356: alpar@1356: nodes[n].next = first_node; alpar@1356: if (first_node != -1) nodes[first_node].prev = n; alpar@1356: first_node = n; alpar@1356: nodes[n].prev = -1; alpar@1356: alpar@1356: nodes[n].partition_next = first_red; alpar@1356: if (first_red != -1) nodes[first_red].partition_prev = n; alpar@1356: first_red = n; alpar@1356: nodes[n].partition_prev = -1; alpar@1356: alpar@1356: nodes[n].first_out = -1; alpar@1356: alpar@1356: return RedNode(n); alpar@1356: } alpar@1356: alpar@1356: BlueNode addBlueNode() { alpar@1356: int n; alpar@1356: alpar@1356: if(first_free_blue==-1) { alpar@1356: n = nodes.size(); alpar@1356: nodes.push_back(NodeT()); alpar@1356: nodes[n].partition_index = ++max_blue; alpar@1356: nodes[n].red = false; alpar@1356: } else { alpar@1356: n = first_free_blue; alpar@1356: first_free_blue = nodes[n].next; alpar@1356: } alpar@1356: alpar@1356: nodes[n].next = first_node; alpar@1356: if (first_node != -1) nodes[first_node].prev = n; alpar@1356: first_node = n; alpar@1356: nodes[n].prev = -1; alpar@1356: alpar@1356: nodes[n].partition_next = first_blue; alpar@1356: if (first_blue != -1) nodes[first_blue].partition_prev = n; alpar@1356: first_blue = n; alpar@1356: nodes[n].partition_prev = -1; alpar@1356: alpar@1356: nodes[n].first_out = -1; alpar@1356: alpar@1356: return BlueNode(n); alpar@1356: } alpar@1356: alpar@1356: Edge addEdge(Node u, Node v) { alpar@1356: int n; alpar@1356: alpar@1356: if (first_free_arc == -1) { alpar@1356: n = arcs.size(); alpar@1356: arcs.push_back(ArcT()); alpar@1356: arcs.push_back(ArcT()); alpar@1356: } else { alpar@1356: n = first_free_arc; alpar@1356: first_free_arc = arcs[n].next_out; alpar@1356: } alpar@1356: alpar@1356: arcs[n].target = u.id; alpar@1356: arcs[n | 1].target = v.id; alpar@1356: alpar@1356: arcs[n].next_out = nodes[v.id].first_out; alpar@1356: if (nodes[v.id].first_out != -1) { alpar@1356: arcs[nodes[v.id].first_out].prev_out = n; alpar@1356: } alpar@1356: arcs[n].prev_out = -1; alpar@1356: nodes[v.id].first_out = n; alpar@1356: alpar@1356: arcs[n | 1].next_out = nodes[u.id].first_out; alpar@1356: if (nodes[u.id].first_out != -1) { alpar@1356: arcs[nodes[u.id].first_out].prev_out = (n | 1); alpar@1356: } alpar@1356: arcs[n | 1].prev_out = -1; alpar@1356: nodes[u.id].first_out = (n | 1); alpar@1356: alpar@1356: return Edge(n / 2); alpar@1356: } alpar@1356: alpar@1356: void erase(const Node& node) { alpar@1356: int n = node.id; alpar@1356: alpar@1356: if(nodes[n].next != -1) { alpar@1356: nodes[nodes[n].next].prev = nodes[n].prev; alpar@1356: } alpar@1356: alpar@1356: if(nodes[n].prev != -1) { alpar@1356: nodes[nodes[n].prev].next = nodes[n].next; alpar@1356: } else { alpar@1356: first_node = nodes[n].next; alpar@1356: } alpar@1356: alpar@1356: if (nodes[n].partition_next != -1) { alpar@1356: nodes[nodes[n].partition_next].partition_prev = nodes[n].partition_prev; alpar@1356: } alpar@1356: alpar@1356: if (nodes[n].partition_prev != -1) { alpar@1356: nodes[nodes[n].partition_prev].partition_next = nodes[n].partition_next; alpar@1356: } else { alpar@1356: if (nodes[n].red) { alpar@1356: first_red = nodes[n].partition_next; alpar@1356: } else { alpar@1356: first_blue = nodes[n].partition_next; alpar@1356: } alpar@1356: } alpar@1356: alpar@1356: if (nodes[n].red) { alpar@1356: nodes[n].next = first_free_red; alpar@1356: first_free_red = n; alpar@1356: } else { alpar@1356: nodes[n].next = first_free_blue; alpar@1356: first_free_blue = n; alpar@1356: } alpar@1356: nodes[n].prev = -2; alpar@1356: } alpar@1356: alpar@1356: void erase(const Edge& edge) { alpar@1356: int n = edge.id * 2; alpar@1356: alpar@1356: if (arcs[n].next_out != -1) { alpar@1356: arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; alpar@1356: } alpar@1356: alpar@1356: if (arcs[n].prev_out != -1) { alpar@1356: arcs[arcs[n].prev_out].next_out = arcs[n].next_out; alpar@1356: } else { alpar@1356: nodes[arcs[n | 1].target].first_out = arcs[n].next_out; alpar@1356: } alpar@1356: alpar@1356: if (arcs[n | 1].next_out != -1) { alpar@1356: arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out; alpar@1356: } alpar@1356: alpar@1356: if (arcs[n | 1].prev_out != -1) { alpar@1356: arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out; alpar@1356: } else { alpar@1356: nodes[arcs[n].target].first_out = arcs[n | 1].next_out; alpar@1356: } alpar@1356: alpar@1356: arcs[n].next_out = first_free_arc; alpar@1356: first_free_arc = n; alpar@1356: arcs[n].prev_out = -2; alpar@1356: arcs[n | 1].prev_out = -2; alpar@1356: alpar@1356: } alpar@1356: alpar@1356: void clear() { alpar@1356: arcs.clear(); alpar@1356: nodes.clear(); alpar@1356: first_node = first_free_arc = first_red = first_blue = alpar@1356: max_red = max_blue = first_free_red = first_free_blue = -1; alpar@1356: } alpar@1356: alpar@1356: protected: alpar@1356: alpar@1356: void changeRed(Edge e, RedNode n) { alpar@1356: if(arcs[(2 * e.id) | 1].next_out != -1) { alpar@1356: arcs[arcs[(2 * e.id) | 1].next_out].prev_out = alpar@1356: arcs[(2 * e.id) | 1].prev_out; alpar@1356: } alpar@1356: if(arcs[(2 * e.id) | 1].prev_out != -1) { alpar@1356: arcs[arcs[(2 * e.id) | 1].prev_out].next_out = alpar@1356: arcs[(2 * e.id) | 1].next_out; alpar@1356: } else { alpar@1356: nodes[arcs[2 * e.id].target].first_out = alpar@1356: arcs[(2 * e.id) | 1].next_out; alpar@1356: } alpar@1356: alpar@1356: if (nodes[n.id].first_out != -1) { alpar@1356: arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); alpar@1356: } alpar@1356: arcs[2 * e.id].target = n.id; alpar@1356: arcs[(2 * e.id) | 1].prev_out = -1; alpar@1356: arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out; alpar@1356: nodes[n.id].first_out = ((2 * e.id) | 1); alpar@1356: } alpar@1356: alpar@1356: void changeBlue(Edge e, BlueNode n) { alpar@1356: if(arcs[2 * e.id].next_out != -1) { alpar@1356: arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out; alpar@1356: } alpar@1356: if(arcs[2 * e.id].prev_out != -1) { alpar@1356: arcs[arcs[2 * e.id].prev_out].next_out = alpar@1356: arcs[2 * e.id].next_out; alpar@1356: } else { alpar@1356: nodes[arcs[(2 * e.id) | 1].target].first_out = alpar@1356: arcs[2 * e.id].next_out; alpar@1356: } alpar@1356: alpar@1356: if (nodes[n.id].first_out != -1) { alpar@1356: arcs[nodes[n.id].first_out].prev_out = 2 * e.id; alpar@1356: } alpar@1356: arcs[(2 * e.id) | 1].target = n.id; alpar@1356: arcs[2 * e.id].prev_out = -1; alpar@1356: arcs[2 * e.id].next_out = nodes[n.id].first_out; alpar@1356: nodes[n.id].first_out = 2 * e.id; alpar@1356: } alpar@1356: alpar@1356: }; alpar@1356: alpar@1356: typedef BpGraphExtender ExtendedListBpGraphBase; alpar@1356: alpar@1356: alpar@1356: /// \addtogroup graphs alpar@1356: /// @{ alpar@1356: alpar@1356: ///A general undirected graph structure. alpar@1356: alpar@1356: ///\ref ListBpGraph is a versatile and fast undirected graph alpar@1356: ///implementation based on linked lists that are stored in alpar@1356: ///\c std::vector structures. alpar@1356: /// alpar@1356: ///This type fully conforms to the \ref concepts::BpGraph "BpGraph concept" alpar@1356: ///and it also provides several useful additional functionalities. alpar@1356: ///Most of its member functions and nested classes are documented alpar@1356: ///only in the concept class. alpar@1356: /// alpar@1356: ///This class provides only linear time counting for nodes, edges and arcs. alpar@1356: /// alpar@1356: ///\sa concepts::BpGraph alpar@1356: ///\sa ListDigraph alpar@1356: class ListBpGraph : public ExtendedListBpGraphBase { alpar@1356: typedef ExtendedListBpGraphBase Parent; alpar@1356: alpar@1356: private: alpar@1356: /// BpGraphs are \e not copy constructible. Use BpGraphCopy instead. alpar@1356: ListBpGraph(const ListBpGraph &) :ExtendedListBpGraphBase() {}; alpar@1356: /// \brief Assignment of a graph to another one is \e not allowed. alpar@1356: /// Use BpGraphCopy instead. alpar@1356: void operator=(const ListBpGraph &) {} alpar@1356: public: alpar@1356: /// Constructor alpar@1356: alpar@1356: /// Constructor. alpar@1356: /// alpar@1356: ListBpGraph() {} alpar@1356: alpar@1356: typedef Parent::OutArcIt IncEdgeIt; alpar@1356: alpar@1356: /// \brief Add a new red node to the graph. alpar@1356: /// alpar@1356: /// This function adds a red new node to the graph. alpar@1356: /// \return The new node. alpar@1356: RedNode addRedNode() { return Parent::addRedNode(); } alpar@1356: alpar@1356: /// \brief Add a new blue node to the graph. alpar@1356: /// alpar@1356: /// This function adds a blue new node to the graph. alpar@1356: /// \return The new node. alpar@1356: BlueNode addBlueNode() { return Parent::addBlueNode(); } alpar@1356: alpar@1356: /// \brief Add a new edge to the graph. alpar@1356: /// alpar@1356: /// This function adds a new edge to the graph between nodes alpar@1356: /// \c u and \c v with inherent orientation from node \c u to alpar@1356: /// node \c v. alpar@1356: /// \return The new edge. alpar@1356: Edge addEdge(RedNode u, BlueNode v) { alpar@1356: return Parent::addEdge(u, v); alpar@1356: } alpar@1356: Edge addEdge(BlueNode v, RedNode u) { alpar@1356: return Parent::addEdge(u, v); alpar@1356: } alpar@1356: alpar@1356: ///\brief Erase a node from the graph. alpar@1356: /// alpar@1356: /// This function erases the given node along with its incident arcs alpar@1356: /// from the graph. alpar@1356: /// alpar@1356: /// \note All iterators referencing the removed node or the incident alpar@1356: /// edges are invalidated, of course. alpar@1356: void erase(Node n) { Parent::erase(n); } alpar@1356: alpar@1356: ///\brief Erase an edge from the graph. alpar@1356: /// alpar@1356: /// This function erases the given edge from the graph. alpar@1356: /// alpar@1356: /// \note All iterators referencing the removed edge are invalidated, alpar@1356: /// of course. alpar@1356: void erase(Edge e) { Parent::erase(e); } alpar@1356: /// Node validity check alpar@1356: alpar@1356: /// This function gives back \c true if the given node is valid, alpar@1356: /// i.e. it is a real node of the graph. alpar@1356: /// alpar@1356: /// \warning A removed node could become valid again if new nodes are alpar@1356: /// added to the graph. alpar@1356: bool valid(Node n) const { return Parent::valid(n); } alpar@1356: /// Edge validity check alpar@1356: alpar@1356: /// This function gives back \c true if the given edge is valid, alpar@1356: /// i.e. it is a real edge of the graph. alpar@1356: /// alpar@1356: /// \warning A removed edge could become valid again if new edges are alpar@1356: /// added to the graph. alpar@1356: bool valid(Edge e) const { return Parent::valid(e); } alpar@1356: /// Arc validity check alpar@1356: alpar@1356: /// This function gives back \c true if the given arc is valid, alpar@1356: /// i.e. it is a real arc of the graph. alpar@1356: /// alpar@1356: /// \warning A removed arc could become valid again if new edges are alpar@1356: /// added to the graph. alpar@1356: bool valid(Arc a) const { return Parent::valid(a); } alpar@1356: alpar@1356: /// \brief Change the red node of an edge. alpar@1356: /// alpar@1356: /// This function changes the red node of the given edge \c e to \c n. alpar@1356: /// alpar@1356: ///\note \c EdgeIt and \c ArcIt iterators referencing the alpar@1356: ///changed edge are invalidated and all other iterators whose alpar@1356: ///base node is the changed node are also invalidated. alpar@1356: /// alpar@1356: ///\warning This functionality cannot be used together with the alpar@1356: ///Snapshot feature. alpar@1356: void changeRed(Edge e, RedNode n) { alpar@1356: Parent::changeRed(e, n); alpar@1356: } alpar@1356: /// \brief Change the blue node of an edge. alpar@1356: /// alpar@1356: /// This function changes the blue node of the given edge \c e to \c n. alpar@1356: /// alpar@1356: ///\note \c EdgeIt iterators referencing the changed edge remain alpar@1356: ///valid, but \c ArcIt iterators referencing the changed edge and alpar@1356: ///all other iterators whose base node is the changed node are also alpar@1356: ///invalidated. alpar@1356: /// alpar@1356: ///\warning This functionality cannot be used together with the alpar@1356: ///Snapshot feature. alpar@1356: void changeBlue(Edge e, BlueNode n) { alpar@1356: Parent::changeBlue(e, n); alpar@1356: } alpar@1356: alpar@1356: ///Clear the graph. alpar@1356: alpar@1356: ///This function erases all nodes and arcs from the graph. alpar@1356: /// alpar@1356: ///\note All iterators of the graph are invalidated, of course. alpar@1356: void clear() { alpar@1356: Parent::clear(); alpar@1356: } alpar@1356: alpar@1356: /// Reserve memory for nodes. alpar@1356: alpar@1356: /// Using this function, it is possible to avoid superfluous memory alpar@1356: /// allocation: if you know that the graph you want to build will alpar@1356: /// be large (e.g. it will contain millions of nodes and/or edges), alpar@1356: /// then it is worth reserving space for this amount before starting alpar@1356: /// to build the graph. alpar@1356: /// \sa reserveEdge() alpar@1356: void reserveNode(int n) { nodes.reserve(n); }; alpar@1356: alpar@1356: /// Reserve memory for edges. alpar@1356: alpar@1356: /// Using this function, it is possible to avoid superfluous memory alpar@1356: /// allocation: if you know that the graph you want to build will alpar@1356: /// be large (e.g. it will contain millions of nodes and/or edges), alpar@1356: /// then it is worth reserving space for this amount before starting alpar@1356: /// to build the graph. alpar@1356: /// \sa reserveNode() alpar@1356: void reserveEdge(int m) { arcs.reserve(2 * m); }; alpar@1356: alpar@1356: /// \brief Class to make a snapshot of the graph and restore alpar@1356: /// it later. alpar@1356: /// alpar@1356: /// Class to make a snapshot of the graph and restore it later. alpar@1356: /// alpar@1356: /// The newly added nodes and edges can be removed alpar@1356: /// using the restore() function. alpar@1356: /// alpar@1356: /// \note After a state is restored, you cannot restore a later state, alpar@1356: /// i.e. you cannot add the removed nodes and edges again using alpar@1356: /// another Snapshot instance. alpar@1356: /// alpar@1356: /// \warning Node and edge deletions and other modifications alpar@1356: /// (e.g. changing the end-nodes of edges or contracting nodes) alpar@1356: /// cannot be restored. These events invalidate the snapshot. alpar@1356: /// However, the edges and nodes that were added to the graph after alpar@1356: /// making the current snapshot can be removed without invalidating it. alpar@1356: class Snapshot { alpar@1356: protected: alpar@1356: alpar@1356: typedef Parent::NodeNotifier NodeNotifier; alpar@1356: alpar@1356: class NodeObserverProxy : public NodeNotifier::ObserverBase { alpar@1356: public: alpar@1356: alpar@1356: NodeObserverProxy(Snapshot& _snapshot) alpar@1356: : snapshot(_snapshot) {} alpar@1356: alpar@1356: using NodeNotifier::ObserverBase::attach; alpar@1356: using NodeNotifier::ObserverBase::detach; alpar@1356: using NodeNotifier::ObserverBase::attached; alpar@1356: alpar@1356: protected: alpar@1356: alpar@1356: virtual void add(const Node& node) { alpar@1356: snapshot.addNode(node); alpar@1356: } alpar@1356: virtual void add(const std::vector& nodes) { alpar@956: for (int i = nodes.size() - 1; i >= 0; ++i) { alpar@956: snapshot.addNode(nodes[i]); alpar@956: } alpar@956: } alpar@956: virtual void erase(const Node& node) { alpar@956: snapshot.eraseNode(node); alpar@956: } alpar@956: virtual void erase(const std::vector& nodes) { alpar@956: for (int i = 0; i < int(nodes.size()); ++i) { alpar@956: snapshot.eraseNode(nodes[i]); alpar@956: } alpar@956: } alpar@956: virtual void build() { alpar@956: Node node; alpar@956: std::vector nodes; alpar@956: for (notifier()->first(node); node != INVALID; alpar@956: notifier()->next(node)) { alpar@956: nodes.push_back(node); alpar@956: } alpar@956: for (int i = nodes.size() - 1; i >= 0; --i) { alpar@956: snapshot.addNode(nodes[i]); alpar@956: } alpar@956: } alpar@956: virtual void clear() { alpar@956: Node node; alpar@956: for (notifier()->first(node); node != INVALID; alpar@956: notifier()->next(node)) { alpar@956: snapshot.eraseNode(node); alpar@956: } alpar@956: } alpar@956: alpar@956: Snapshot& snapshot; alpar@956: }; alpar@956: alpar@956: class EdgeObserverProxy : public EdgeNotifier::ObserverBase { alpar@956: public: alpar@956: alpar@956: EdgeObserverProxy(Snapshot& _snapshot) alpar@956: : snapshot(_snapshot) {} alpar@956: alpar@956: using EdgeNotifier::ObserverBase::attach; alpar@956: using EdgeNotifier::ObserverBase::detach; alpar@956: using EdgeNotifier::ObserverBase::attached; alpar@956: alpar@956: protected: alpar@956: alpar@956: virtual void add(const Edge& edge) { alpar@956: snapshot.addEdge(edge); alpar@956: } alpar@956: virtual void add(const std::vector& edges) { alpar@956: for (int i = edges.size() - 1; i >= 0; ++i) { alpar@956: snapshot.addEdge(edges[i]); alpar@956: } alpar@956: } alpar@956: virtual void erase(const Edge& edge) { alpar@956: snapshot.eraseEdge(edge); alpar@956: } alpar@956: virtual void erase(const std::vector& edges) { alpar@956: for (int i = 0; i < int(edges.size()); ++i) { alpar@956: snapshot.eraseEdge(edges[i]); alpar@956: } alpar@956: } alpar@956: virtual void build() { alpar@956: Edge edge; alpar@956: std::vector edges; alpar@956: for (notifier()->first(edge); edge != INVALID; alpar@956: notifier()->next(edge)) { alpar@956: edges.push_back(edge); alpar@956: } alpar@956: for (int i = edges.size() - 1; i >= 0; --i) { alpar@956: snapshot.addEdge(edges[i]); alpar@956: } alpar@956: } alpar@956: virtual void clear() { alpar@956: Edge edge; alpar@956: for (notifier()->first(edge); edge != INVALID; alpar@956: notifier()->next(edge)) { alpar@956: snapshot.eraseEdge(edge); alpar@956: } alpar@956: } alpar@956: alpar@956: Snapshot& snapshot; alpar@956: }; alpar@956: deba@1189: ListBpGraph *graph; deba@1189: deba@1189: NodeObserverProxy node_observer_proxy; deba@1189: EdgeObserverProxy edge_observer_proxy; deba@1189: deba@1189: std::list added_nodes; deba@1189: std::list added_edges; deba@1189: deba@1189: deba@1189: void addNode(const Node& node) { deba@1189: added_nodes.push_front(node); deba@1189: } deba@1189: void eraseNode(const Node& node) { deba@1189: std::list::iterator it = deba@1189: std::find(added_nodes.begin(), added_nodes.end(), node); deba@1189: if (it == added_nodes.end()) { deba@1189: clear(); deba@1189: edge_observer_proxy.detach(); deba@1189: throw NodeNotifier::ImmediateDetach(); deba@1189: } else { deba@1189: added_nodes.erase(it); deba@1189: } deba@1189: } deba@1189: deba@1189: void addEdge(const Edge& edge) { deba@1189: added_edges.push_front(edge); deba@1189: } deba@1189: void eraseEdge(const Edge& edge) { deba@1189: std::list::iterator it = deba@1189: std::find(added_edges.begin(), added_edges.end(), edge); deba@1189: if (it == added_edges.end()) { deba@1189: clear(); deba@1189: node_observer_proxy.detach(); deba@1189: throw EdgeNotifier::ImmediateDetach(); deba@1189: } else { deba@1189: added_edges.erase(it); deba@1189: } deba@1189: } deba@1189: deba@1189: void attach(ListBpGraph &_graph) { deba@1189: graph = &_graph; deba@1189: node_observer_proxy.attach(graph->notifier(Node())); deba@1189: edge_observer_proxy.attach(graph->notifier(Edge())); deba@1189: } deba@1189: deba@1189: void detach() { deba@1189: node_observer_proxy.detach(); deba@1189: edge_observer_proxy.detach(); deba@1189: } deba@1189: deba@1189: bool attached() const { deba@1189: return node_observer_proxy.attached(); deba@1189: } deba@1189: deba@1189: void clear() { deba@1189: added_nodes.clear(); deba@1189: added_edges.clear(); deba@1189: } deba@1189: deba@1189: public: deba@1189: deba@1189: /// \brief Default constructor. deba@1189: /// deba@1189: /// Default constructor. deba@1189: /// You have to call save() to actually make a snapshot. deba@1189: Snapshot() deba@1189: : graph(0), node_observer_proxy(*this), deba@1189: edge_observer_proxy(*this) {} deba@1189: deba@1189: /// \brief Constructor that immediately makes a snapshot. deba@1189: /// deba@1189: /// This constructor immediately makes a snapshot of the given graph. deba@1189: Snapshot(ListBpGraph &gr) deba@1189: : node_observer_proxy(*this), deba@1189: edge_observer_proxy(*this) { deba@1189: attach(gr); deba@1189: } deba@1189: deba@1189: /// \brief Make a snapshot. deba@1189: /// deba@1189: /// This function makes a snapshot of the given graph. deba@1189: /// It can be called more than once. In case of a repeated deba@1189: /// call, the previous snapshot gets lost. deba@1189: void save(ListBpGraph &gr) { deba@1189: if (attached()) { deba@1189: detach(); deba@1189: clear(); deba@1189: } deba@1189: attach(gr); deba@1189: } deba@1189: deba@1189: /// \brief Undo the changes until the last snapshot. deba@1189: /// deba@1189: /// This function undos the changes until the last snapshot deba@1189: /// created by save() or Snapshot(ListBpGraph&). deba@1189: /// deba@1189: /// \warning This method invalidates the snapshot, i.e. repeated deba@1189: /// restoring is not supported unless you call save() again. deba@1189: void restore() { deba@1189: detach(); deba@1189: for(std::list::iterator it = added_edges.begin(); deba@1189: it != added_edges.end(); ++it) { deba@1189: graph->erase(*it); deba@1189: } deba@1189: for(std::list::iterator it = added_nodes.begin(); deba@1189: it != added_nodes.end(); ++it) { deba@1189: graph->erase(*it); deba@1189: } deba@1189: clear(); deba@1189: } deba@1189: deba@1189: /// \brief Returns \c true if the snapshot is valid. deba@1189: /// deba@1189: /// This function returns \c true if the snapshot is valid. deba@1189: bool valid() const { deba@1189: return attached(); deba@1189: } deba@1189: }; deba@1189: }; deba@1189: deba@1189: /// @} deba@57: } //namespace lemon alpar@209: deba@57: deba@57: #endif