alpar@948: /* -*- C++ -*- alpar@948: * alpar@1956: * This file is a part of LEMON, a generic C++ optimization library alpar@1956: * alpar@2553: * Copyright (C) 2003-2008 alpar@1956: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1359: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@948: * alpar@948: * Permission to use, modify and distribute this software is granted alpar@948: * provided that this copyright notice appears in all copies. For alpar@948: * precise terms see the accompanying LICENSE file. alpar@948: * alpar@948: * This software is provided "AS IS" with no warranty of any kind, alpar@948: * express or implied, and with no claim as to its suitability for any alpar@948: * purpose. alpar@948: * alpar@948: */ alpar@395: alpar@921: #ifndef LEMON_LIST_GRAPH_H alpar@921: #define LEMON_LIST_GRAPH_H alpar@395: alpar@948: ///\ingroup graphs alpar@948: ///\file deba@2116: ///\brief ListGraph, ListUGraph classes. alpar@948: deba@2116: #include deba@1791: #include deba@782: deba@2116: #include deba@2116: deba@1979: #include alpar@1011: #include deba@782: alpar@921: namespace lemon { alpar@395: klao@946: class ListGraphBase { alpar@406: alpar@949: protected: klao@946: struct NodeT { deba@1470: int first_in, first_out; alpar@397: int prev, next; alpar@395: }; klao@946: klao@946: struct EdgeT { alpar@986: int target, source; alpar@397: int prev_in, prev_out; alpar@397: int next_in, next_out; alpar@395: }; alpar@395: alpar@395: std::vector nodes; klao@946: alpar@397: int first_node; klao@946: alpar@397: int first_free_node; klao@946: alpar@395: std::vector edges; klao@946: alpar@397: int first_free_edge; alpar@395: deba@782: public: alpar@395: klao@946: typedef ListGraphBase Graph; alpar@397: klao@946: class Node { marci@975: friend class ListGraphBase; klao@946: protected: alpar@395: klao@946: int id; deba@2031: explicit Node(int pid) { id = pid;} alpar@395: klao@946: public: klao@946: Node() {} klao@946: Node (Invalid) { id = -1; } klao@946: bool operator==(const Node& node) const {return id == node.id;} klao@946: bool operator!=(const Node& node) const {return id != node.id;} klao@946: bool operator<(const Node& node) const {return id < node.id;} klao@946: }; deba@782: klao@946: class Edge { marci@975: friend class ListGraphBase; klao@946: protected: deba@782: klao@946: int id; deba@2031: explicit Edge(int pid) { id = pid;} alpar@395: klao@946: public: klao@946: Edge() {} klao@946: Edge (Invalid) { id = -1; } klao@946: bool operator==(const Edge& edge) const {return id == edge.id;} klao@946: bool operator!=(const Edge& edge) const {return id != edge.id;} klao@946: bool operator<(const Edge& edge) const {return id < edge.id;} klao@946: }; klao@946: klao@946: klao@946: klao@946: ListGraphBase() deba@782: : nodes(), first_node(-1), deba@782: first_free_node(-1), edges(), first_free_edge(-1) {} deba@782: alpar@395: deba@1791: int maxNodeId() const { return nodes.size()-1; } deba@1791: int maxEdgeId() const { return edges.size()-1; } alpar@395: deba@2031: Node source(Edge e) const { return Node(edges[e.id].source); } deba@2031: Node target(Edge e) const { return Node(edges[e.id].target); } alpar@395: alpar@395: klao@946: void first(Node& node) const { klao@946: node.id = first_node; klao@946: } klao@946: klao@946: void next(Node& node) const { klao@946: node.id = nodes[node.id].next; klao@946: } klao@946: klao@946: klao@946: void first(Edge& e) const { klao@946: int n; klao@946: for(n = first_node; klao@946: n!=-1 && nodes[n].first_in == -1; klao@946: n = nodes[n].next); klao@946: e.id = (n == -1) ? -1 : nodes[n].first_in; klao@946: } klao@946: klao@946: void next(Edge& edge) const { klao@946: if (edges[edge.id].next_in != -1) { klao@946: edge.id = edges[edge.id].next_in; klao@946: } else { klao@946: int n; alpar@986: for(n = nodes[edges[edge.id].target].next; klao@946: n!=-1 && nodes[n].first_in == -1; klao@946: n = nodes[n].next); klao@946: edge.id = (n == -1) ? -1 : nodes[n].first_in; klao@946: } klao@946: } klao@946: klao@946: void firstOut(Edge &e, const Node& v) const { klao@946: e.id = nodes[v.id].first_out; klao@946: } klao@946: void nextOut(Edge &e) const { klao@946: e.id=edges[e.id].next_out; klao@946: } klao@946: klao@946: void firstIn(Edge &e, const Node& v) const { klao@946: e.id = nodes[v.id].first_in; klao@946: } klao@946: void nextIn(Edge &e) const { klao@946: e.id=edges[e.id].next_in; klao@946: } klao@946: alpar@813: klao@946: static int id(Node v) { return v.id; } klao@946: static int id(Edge e) { return e.id; } alpar@395: deba@1791: static Node nodeFromId(int id) { return Node(id);} deba@1791: static Edge edgeFromId(int id) { return Edge(id);} deba@1106: klao@946: Node addNode() { alpar@397: int n; alpar@397: klao@946: if(first_free_node==-1) { klao@946: n = nodes.size(); klao@946: nodes.push_back(NodeT()); klao@946: } else { alpar@397: n = first_free_node; alpar@397: first_free_node = nodes[n].next; alpar@397: } alpar@397: alpar@397: nodes[n].next = first_node; alpar@397: if(first_node != -1) nodes[first_node].prev = n; alpar@397: first_node = n; alpar@397: nodes[n].prev = -1; alpar@397: alpar@397: nodes[n].first_in = nodes[n].first_out = -1; alpar@397: klao@946: return Node(n); alpar@395: } alpar@395: alpar@395: Edge addEdge(Node u, Node v) { klao@946: int n; klao@946: klao@946: if (first_free_edge == -1) { klao@946: n = edges.size(); klao@946: edges.push_back(EdgeT()); klao@946: } else { alpar@397: n = first_free_edge; alpar@397: first_free_edge = edges[n].next_in; alpar@397: } alpar@397: alpar@986: edges[n].source = u.id; alpar@986: edges[n].target = v.id; alpar@395: klao@946: edges[n].next_out = nodes[u.id].first_out; klao@946: if(nodes[u.id].first_out != -1) { klao@946: edges[nodes[u.id].first_out].prev_out = n; klao@946: } klao@946: klao@946: edges[n].next_in = nodes[v.id].first_in; klao@946: if(nodes[v.id].first_in != -1) { klao@946: edges[nodes[v.id].first_in].prev_in = n; klao@946: } klao@946: alpar@397: edges[n].prev_in = edges[n].prev_out = -1; alpar@397: klao@946: nodes[u.id].first_out = nodes[v.id].first_in = n; alpar@397: klao@946: return Edge(n); alpar@395: } alpar@774: klao@946: void erase(const Node& node) { klao@946: int n = node.id; klao@946: klao@946: if(nodes[n].next != -1) { klao@946: nodes[nodes[n].next].prev = nodes[n].prev; klao@946: } klao@946: klao@946: if(nodes[n].prev != -1) { klao@946: nodes[nodes[n].prev].next = nodes[n].next; klao@946: } else { klao@946: first_node = nodes[n].next; klao@946: } klao@946: klao@946: nodes[n].next = first_free_node; klao@946: first_free_node = n; alpar@395: alpar@774: } alpar@774: klao@946: void erase(const Edge& edge) { klao@946: int n = edge.id; alpar@397: klao@946: if(edges[n].next_in!=-1) { alpar@397: edges[edges[n].next_in].prev_in = edges[n].prev_in; klao@946: } klao@946: klao@946: if(edges[n].prev_in!=-1) { alpar@397: edges[edges[n].prev_in].next_in = edges[n].next_in; klao@946: } else { alpar@986: nodes[edges[n].target].first_in = edges[n].next_in; klao@946: } klao@946: alpar@397: klao@946: if(edges[n].next_out!=-1) { alpar@397: edges[edges[n].next_out].prev_out = edges[n].prev_out; klao@946: } klao@946: klao@946: if(edges[n].prev_out!=-1) { alpar@397: edges[edges[n].prev_out].next_out = edges[n].next_out; klao@946: } else { alpar@986: nodes[edges[n].source].first_out = edges[n].next_out; klao@946: } alpar@397: alpar@397: edges[n].next_in = first_free_edge; alpar@695: first_free_edge = n; alpar@397: alpar@397: } alpar@397: alpar@397: void clear() { deba@782: edges.clear(); deba@782: nodes.clear(); klao@946: first_node = first_free_node = first_free_edge = -1; deba@937: } deba@937: alpar@949: protected: deba@2111: void changeTarget(Edge e, Node n) alpar@949: { alpar@949: if(edges[e.id].next_in != -1) alpar@949: edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in; alpar@949: if(edges[e.id].prev_in != -1) alpar@949: edges[edges[e.id].prev_in].next_in = edges[e.id].next_in; alpar@986: else nodes[edges[e.id].target].first_in = edges[e.id].next_in; deba@1702: if (nodes[n.id].first_in != -1) { deba@1702: edges[nodes[n.id].first_in].prev_in = e.id; deba@1702: } alpar@986: edges[e.id].target = n.id; alpar@949: edges[e.id].prev_in = -1; alpar@949: edges[e.id].next_in = nodes[n.id].first_in; alpar@949: nodes[n.id].first_in = e.id; alpar@949: } deba@2111: void changeSource(Edge e, Node n) alpar@949: { alpar@949: if(edges[e.id].next_out != -1) alpar@949: edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out; alpar@949: if(edges[e.id].prev_out != -1) alpar@949: edges[edges[e.id].prev_out].next_out = edges[e.id].next_out; alpar@986: else nodes[edges[e.id].source].first_out = edges[e.id].next_out; deba@1702: if (nodes[n.id].first_out != -1) { deba@1702: edges[nodes[n.id].first_out].prev_out = e.id; deba@1702: } alpar@986: edges[e.id].source = n.id; alpar@949: edges[e.id].prev_out = -1; alpar@949: edges[e.id].next_out = nodes[n.id].first_out; alpar@949: nodes[n.id].first_out = e.id; alpar@949: } alpar@949: alpar@919: }; deba@909: deba@1979: typedef GraphExtender ExtendedListGraphBase; alpar@400: deba@2116: /// \addtogroup graphs deba@2116: /// @{ alpar@400: alpar@948: ///A list graph class. alpar@400: alpar@2117: ///This is a simple and fast graph implementation. alpar@948: /// alpar@2260: ///It conforms to the \ref concepts::Graph "Graph concept" and it deba@2111: ///also provides several additional useful extra functionalities. deba@2111: ///The most of the member functions and nested classes are deba@2111: ///documented only in the concept class. alpar@2256: /// alpar@2256: ///An important extra feature of this graph implementation is that alpar@2260: ///its maps are real \ref concepts::ReferenceMap "reference map"s. alpar@2256: /// alpar@2260: ///\sa concepts::Graph. deba@782: deba@1999: class ListGraph : public ExtendedListGraphBase { alpar@2128: private: alpar@2128: ///ListGraph is \e not copy constructible. Use GraphCopy() instead. alpar@2128: alpar@2128: ///ListGraph is \e not copy constructible. Use GraphCopy() instead. alpar@2128: /// alpar@2128: ListGraph(const ListGraph &) :ExtendedListGraphBase() {}; alpar@2132: ///\brief Assignment of ListGraph to another one is \e not allowed. alpar@2128: ///Use GraphCopy() instead. alpar@2128: alpar@2132: ///Assignment of ListGraph to another one is \e not allowed. alpar@2128: ///Use GraphCopy() instead. alpar@2128: void operator=(const ListGraph &) {} alpar@948: public: deba@1999: deba@1999: typedef ExtendedListGraphBase Parent; deba@1999: alpar@2128: /// Constructor alpar@2128: alpar@2128: /// Constructor. alpar@2128: /// alpar@2128: ListGraph() {} alpar@2128: deba@2111: ///Add a new node to the graph. deba@2111: deba@2111: /// \return the new node. deba@2111: /// deba@2111: Node addNode() { return Parent::addNode(); } deba@2111: deba@2111: ///Add a new edge to the graph. deba@2111: deba@2111: ///Add a new edge to the graph with source node \c s deba@2111: ///and target node \c t. deba@2111: ///\return the new edge. deba@2111: Edge addEdge(const Node& s, const Node& t) { deba@2111: return Parent::addEdge(s, t); deba@2111: } deba@2111: alpar@1546: /// Changes the target of \c e to \c n alpar@948: alpar@1546: /// Changes the target of \c e to \c n alpar@948: /// deba@2160: ///\note The EdgeIts and OutEdgeIts referencing deba@2114: ///the changed edge remain valid. However InEdgeIts are deba@2114: ///invalidated. alpar@2123: ///\warning This functionality cannot be used together with the Snapshot alpar@2123: ///feature. deba@1718: void changeTarget(Edge e, Node n) { deba@2111: Parent::changeTarget(e,n); deba@1718: } alpar@1546: /// Changes the source of \c e to \c n alpar@948: alpar@1546: /// Changes the source of \c e to \c n alpar@948: /// deba@2160: ///\note The EdgeIts and InEdgeIts referencing deba@2114: ///the changed edge remain valid. However OutEdgeIts are deba@2114: ///invalidated. alpar@2123: ///\warning This functionality cannot be used together with the Snapshot alpar@2123: ///feature. deba@1718: void changeSource(Edge e, Node n) { deba@2111: Parent::changeSource(e,n); deba@1718: } alpar@949: alpar@1010: /// Invert the direction of an edge. alpar@1010: deba@2160: ///\note The EdgeIts referencing the changed edge remain deba@2114: ///valid. However OutEdgeIts and InEdgeIts are deba@2114: ///invalidated. alpar@2123: ///\warning This functionality cannot be used together with the Snapshot alpar@2123: ///feature. alpar@1010: void reverseEdge(Edge e) { alpar@1010: Node t=target(e); deba@2111: changeTarget(e,source(e)); deba@2111: changeSource(e,t); alpar@1010: } alpar@1010: deba@2456: /// Using this it is possible to avoid the superfluous memory deba@2456: /// allocation: if you know that the graph you want to build will deba@2456: /// be very large (e.g. it will contain millions of nodes and/or edges) deba@2456: /// then it is worth reserving space for this amount before starting deba@2456: /// to build the graph. deba@2456: /// \sa reserveEdge deba@2107: void reserveNode(int n) { nodes.reserve(n); }; deba@2107: deba@2111: /// \brief Using this it is possible to avoid the superfluous memory deba@2111: /// allocation. deba@2107: deba@2456: /// Using this it is possible to avoid the superfluous memory deba@2456: /// allocation: if you know that the graph you want to build will deba@2456: /// be very large (e.g. it will contain millions of nodes and/or edges) deba@2456: /// then it is worth reserving space for this amount before starting deba@2456: /// to build the graph. deba@2456: /// \sa reserveNode deba@2456: void reserveEdge(int m) { edges.reserve(m); }; deba@2107: alpar@1010: ///Contract two nodes. alpar@1010: alpar@1010: ///This function contracts two nodes. alpar@1010: /// alpar@1010: ///Node \p b will be removed but instead of deleting athos@2102: ///incident edges, they will be joined to \p a. alpar@1010: ///The last parameter \p r controls whether to remove loops. \c true alpar@1010: ///means that loops will be removed. alpar@1010: /// deba@2160: ///\note The EdgeIts alpar@1281: ///referencing a moved edge remain deba@2160: ///valid. However InEdgeIts and OutEdgeIts alpar@1010: ///may be invalidated. alpar@2123: ///\warning This functionality cannot be used together with the Snapshot alpar@2123: ///feature. deba@1718: void contract(Node a, Node b, bool r = true) alpar@1010: { alpar@1010: for(OutEdgeIt e(*this,b);e!=INVALID;) { alpar@1010: OutEdgeIt f=e; alpar@1010: ++f; alpar@1010: if(r && target(e)==a) erase(e); alpar@1546: else changeSource(e,a); alpar@1010: e=f; alpar@1010: } alpar@1010: for(InEdgeIt e(*this,b);e!=INVALID;) { alpar@1010: InEdgeIt f=e; alpar@1010: ++f; alpar@1010: if(r && source(e)==a) erase(e); alpar@1546: else changeTarget(e,a); alpar@1010: e=f; alpar@1010: } alpar@1010: erase(b); alpar@1010: } alpar@1011: alpar@1281: ///Split a node. alpar@1011: alpar@1284: ///This function splits a node. First a new node is added to the graph, alpar@1284: ///then the source of each outgoing edge of \c n is moved to this new node. alpar@1281: ///If \c connect is \c true (this is the default value), then a new edge alpar@1281: ///from \c n to the newly created node is also added. alpar@1281: ///\return The newly created node. alpar@1281: /// deba@2160: ///\note The EdgeIts referencing a moved edge remain deba@2160: ///valid. However InEdgeIts and OutEdgeIts may deba@2160: ///be invalidated. deba@2160: /// deba@2160: ///\warning This functionality cannot be used together with the deba@2160: ///Snapshot feature. \todo It could be implemented in a bit deba@2160: ///faster way. deba@2114: Node split(Node n, bool connect = true) { alpar@1281: Node b = addNode(); alpar@1281: for(OutEdgeIt e(*this,n);e!=INVALID;) { alpar@1281: OutEdgeIt f=e; alpar@1281: ++f; alpar@1546: changeSource(e,b); alpar@1281: e=f; alpar@1281: } deba@2114: if (connect) addEdge(n,b); alpar@1281: return b; alpar@1281: } alpar@1281: alpar@1812: ///Split an edge. alpar@1812: athos@2102: ///This function splits an edge. First a new node \c b is added to athos@2102: ///the graph, then the original edge is re-targeted to \c athos@2102: ///b. Finally an edge from \c b to the original target is added. athos@2102: ///\return The newly created node. athos@2102: ///\warning This functionality athos@2102: ///cannot be used together with the Snapshot feature. deba@2114: Node split(Edge e) { alpar@1812: Node b = addNode(); alpar@1812: addEdge(b,target(e)); alpar@1812: changeTarget(e,b); alpar@1812: return b; alpar@1812: } alpar@1812: deba@2114: /// \brief Class to make a snapshot of the graph and restore deba@2114: /// to it later. alpar@1011: /// deba@2114: /// Class to make a snapshot of the graph and to restore it deba@2114: /// later. alpar@1011: /// deba@2114: /// The newly added nodes and edges can be removed using the deba@2114: /// restore() function. deba@2114: /// deba@2189: /// \warning Edge and node deletions cannot be restored. This deba@2189: /// events invalidate the snapshot. deba@2114: class Snapshot { deba@1999: protected: deba@2114: deba@2114: typedef Parent::NodeNotifier NodeNotifier; deba@2114: deba@2114: class NodeObserverProxy : public NodeNotifier::ObserverBase { deba@2114: public: deba@2114: deba@2114: NodeObserverProxy(Snapshot& _snapshot) deba@2114: : snapshot(_snapshot) {} deba@2114: deba@2114: using NodeNotifier::ObserverBase::attach; deba@2114: using NodeNotifier::ObserverBase::detach; deba@2114: using NodeNotifier::ObserverBase::attached; deba@2114: deba@2114: protected: deba@2114: deba@2114: virtual void add(const Node& node) { deba@2114: snapshot.addNode(node); deba@2114: } deba@2114: virtual void add(const std::vector& nodes) { deba@2114: for (int i = nodes.size() - 1; i >= 0; ++i) { deba@2114: snapshot.addNode(nodes[i]); deba@2114: } deba@2114: } deba@2114: virtual void erase(const Node& node) { deba@2114: snapshot.eraseNode(node); deba@2114: } deba@2114: virtual void erase(const std::vector& nodes) { deba@2386: for (int i = 0; i < int(nodes.size()); ++i) { deba@2189: snapshot.eraseNode(nodes[i]); deba@2114: } deba@2114: } deba@2114: virtual void build() { deba@2114: Node node; deba@2114: std::vector nodes; deba@2386: for (notifier()->first(node); node != INVALID; deba@2386: notifier()->next(node)) { deba@2114: nodes.push_back(node); deba@2114: } deba@2114: for (int i = nodes.size() - 1; i >= 0; --i) { deba@2114: snapshot.addNode(nodes[i]); deba@2114: } deba@2114: } deba@2114: virtual void clear() { deba@2114: Node node; deba@2386: for (notifier()->first(node); node != INVALID; deba@2386: notifier()->next(node)) { deba@2189: snapshot.eraseNode(node); deba@2114: } deba@2114: } deba@2114: deba@2114: Snapshot& snapshot; deba@2114: }; deba@2114: deba@2114: class EdgeObserverProxy : public EdgeNotifier::ObserverBase { deba@2114: public: deba@2114: deba@2114: EdgeObserverProxy(Snapshot& _snapshot) deba@2114: : snapshot(_snapshot) {} deba@2114: deba@2114: using EdgeNotifier::ObserverBase::attach; deba@2114: using EdgeNotifier::ObserverBase::detach; deba@2114: using EdgeNotifier::ObserverBase::attached; deba@2114: deba@2114: protected: deba@2114: deba@2114: virtual void add(const Edge& edge) { deba@2114: snapshot.addEdge(edge); deba@2114: } deba@2114: virtual void add(const std::vector& edges) { deba@2114: for (int i = edges.size() - 1; i >= 0; ++i) { deba@2114: snapshot.addEdge(edges[i]); deba@2114: } deba@2114: } deba@2114: virtual void erase(const Edge& edge) { deba@2114: snapshot.eraseEdge(edge); deba@2114: } deba@2114: virtual void erase(const std::vector& edges) { deba@2386: for (int i = 0; i < int(edges.size()); ++i) { deba@2189: snapshot.eraseEdge(edges[i]); deba@2114: } deba@2114: } deba@2114: virtual void build() { deba@2114: Edge edge; deba@2114: std::vector edges; deba@2386: for (notifier()->first(edge); edge != INVALID; deba@2386: notifier()->next(edge)) { deba@2114: edges.push_back(edge); deba@2114: } deba@2114: for (int i = edges.size() - 1; i >= 0; --i) { deba@2114: snapshot.addEdge(edges[i]); deba@2114: } deba@2114: } deba@2114: virtual void clear() { deba@2114: Edge edge; deba@2386: for (notifier()->first(edge); edge != INVALID; deba@2386: notifier()->next(edge)) { deba@2189: snapshot.eraseEdge(edge); deba@2114: } deba@2114: } deba@2114: deba@2114: Snapshot& snapshot; deba@2114: }; alpar@1011: deba@2114: ListGraph *graph; deba@2114: deba@2114: NodeObserverProxy node_observer_proxy; deba@2114: EdgeObserverProxy edge_observer_proxy; deba@2114: alpar@1011: std::list added_nodes; alpar@1011: std::list added_edges; deba@2114: deba@2114: deba@2114: void addNode(const Node& node) { deba@2114: added_nodes.push_front(node); alpar@1011: } deba@2189: void eraseNode(const Node& node) { deba@2114: std::list::iterator it = deba@2114: std::find(added_nodes.begin(), added_nodes.end(), node); deba@2114: if (it == added_nodes.end()) { deba@2114: clear(); deba@2189: edge_observer_proxy.detach(); deba@2189: throw NodeNotifier::ImmediateDetach(); deba@2114: } else { deba@2114: added_nodes.erase(it); deba@2114: } alpar@1011: } alpar@1011: deba@2114: void addEdge(const Edge& edge) { deba@2114: added_edges.push_front(edge); deba@2114: } deba@2189: void eraseEdge(const Edge& edge) { deba@2114: std::list::iterator it = deba@2114: std::find(added_edges.begin(), added_edges.end(), edge); deba@2114: if (it == added_edges.end()) { deba@2114: clear(); deba@2189: node_observer_proxy.detach(); deba@2189: throw EdgeNotifier::ImmediateDetach(); deba@2114: } else { deba@2114: added_edges.erase(it); deba@2114: } deba@2114: } alpar@1457: deba@2114: void attach(ListGraph &_graph) { deba@2114: graph = &_graph; deba@2381: node_observer_proxy.attach(graph->notifier(Node())); deba@2381: edge_observer_proxy.attach(graph->notifier(Edge())); alpar@1011: } alpar@1011: deba@2114: void detach() { deba@2114: node_observer_proxy.detach(); deba@2114: edge_observer_proxy.detach(); deba@2114: } deba@2114: deba@2189: bool attached() const { deba@2189: return node_observer_proxy.attached(); deba@2189: } deba@2189: deba@2114: void clear() { deba@2114: added_nodes.clear(); deba@2114: added_edges.clear(); alpar@1011: } deba@1774: alpar@1011: public: deba@2114: deba@2160: /// \brief Default constructor. deba@2114: /// deba@2114: /// Default constructor. deba@2114: /// To actually make a snapshot you must call save(). deba@2114: Snapshot() deba@2114: : graph(0), node_observer_proxy(*this), deba@2114: edge_observer_proxy(*this) {} alpar@1011: deba@2114: /// \brief Constructor that immediately makes a snapshot. deba@2114: /// deba@2114: /// This constructor immediately makes a snapshot of the graph. deba@2114: /// \param _graph The graph we make a snapshot of. deba@2114: Snapshot(ListGraph &_graph) deba@2114: : node_observer_proxy(*this), deba@2114: edge_observer_proxy(*this) { deba@2114: attach(_graph); alpar@1011: } alpar@1011: deba@2114: /// \brief Make a snapshot. alpar@1011: /// deba@2114: /// Make a snapshot of the graph. deba@2114: /// deba@2114: /// This function can be called more than once. In case of a repeated deba@2114: /// call, the previous snapshot gets lost. deba@2114: /// \param _graph The graph we make the snapshot of. deba@2114: void save(ListGraph &_graph) { deba@2189: if (attached()) { deba@2189: detach(); deba@2189: clear(); deba@2189: } deba@2114: attach(_graph); alpar@1011: } alpar@1011: deba@2114: /// \brief Undo the changes until the last snapshot. deba@2114: // alpar@2123: /// Undo the changes until the last snapshot created by save(). alpar@1011: void restore() { deba@2114: detach(); deba@2189: for(std::list::iterator it = added_edges.begin(); deba@2189: it != added_edges.end(); ++it) { deba@2189: graph->erase(*it); alpar@1011: } deba@2189: for(std::list::iterator it = added_nodes.begin(); deba@2189: it != added_nodes.end(); ++it) { deba@2189: graph->erase(*it); alpar@1011: } deba@2189: clear(); alpar@1011: } deba@2114: deba@2114: /// \brief Gives back true when the snapshot is valid. deba@2114: /// deba@2114: /// Gives back true when the snapshot is valid. deba@2114: bool valid() const { deba@2189: return attached(); deba@2114: } alpar@1011: }; alpar@1011: alpar@949: }; klao@1034: deba@2116: ///@} deba@2116: deba@2338: class ListUGraphBase { deba@2116: deba@2338: protected: deba@2338: deba@2338: struct NodeT { deba@2338: int first_out; deba@2338: int prev, next; deba@2338: }; deba@2338: deba@2338: struct EdgeT { deba@2338: int target; deba@2338: int prev_out, next_out; deba@2338: }; deba@2338: deba@2338: std::vector nodes; deba@2338: deba@2338: int first_node; deba@2338: deba@2338: int first_free_node; deba@2338: deba@2338: std::vector edges; deba@2338: deba@2338: int first_free_edge; deba@2338: deba@2338: public: deba@2338: deba@2338: typedef ListUGraphBase Graph; deba@2343: deba@2343: class Node; deba@2343: class Edge; deba@2343: class UEdge; deba@2338: deba@2338: class Node { deba@2338: friend class ListUGraphBase; deba@2338: protected: deba@2338: deba@2338: int id; deba@2338: explicit Node(int pid) { id = pid;} deba@2338: deba@2338: public: deba@2338: Node() {} deba@2338: Node (Invalid) { id = -1; } deba@2338: bool operator==(const Node& node) const {return id == node.id;} deba@2338: bool operator!=(const Node& node) const {return id != node.id;} deba@2338: bool operator<(const Node& node) const {return id < node.id;} deba@2338: }; deba@2338: deba@2338: class UEdge { deba@2338: friend class ListUGraphBase; deba@2338: protected: deba@2338: deba@2338: int id; deba@2338: explicit UEdge(int pid) { id = pid;} deba@2338: deba@2338: public: deba@2338: UEdge() {} deba@2338: UEdge (Invalid) { id = -1; } deba@2338: bool operator==(const UEdge& edge) const {return id == edge.id;} deba@2338: bool operator!=(const UEdge& edge) const {return id != edge.id;} deba@2338: bool operator<(const UEdge& edge) const {return id < edge.id;} deba@2338: }; deba@2338: deba@2338: class Edge { deba@2338: friend class ListUGraphBase; deba@2338: protected: deba@2338: deba@2338: int id; deba@2338: explicit Edge(int pid) { id = pid;} deba@2338: deba@2338: public: deba@2343: operator UEdge() const { return uEdgeFromId(id / 2); } deba@2338: deba@2338: Edge() {} deba@2338: Edge (Invalid) { id = -1; } deba@2338: bool operator==(const Edge& edge) const {return id == edge.id;} deba@2338: bool operator!=(const Edge& edge) const {return id != edge.id;} deba@2338: bool operator<(const Edge& edge) const {return id < edge.id;} deba@2338: }; deba@2338: deba@2338: deba@2338: deba@2338: ListUGraphBase() deba@2338: : nodes(), first_node(-1), deba@2338: first_free_node(-1), edges(), first_free_edge(-1) {} deba@2338: deba@2338: deba@2338: int maxNodeId() const { return nodes.size()-1; } deba@2338: int maxUEdgeId() const { return edges.size() / 2 - 1; } deba@2338: int maxEdgeId() const { return edges.size()-1; } deba@2338: deba@2338: Node source(Edge e) const { return Node(edges[e.id ^ 1].target); } deba@2338: Node target(Edge e) const { return Node(edges[e.id].target); } deba@2338: deba@2338: Node source(UEdge e) const { return Node(edges[2 * e.id].target); } deba@2338: Node target(UEdge e) const { return Node(edges[2 * e.id + 1].target); } deba@2338: deba@2338: static bool direction(Edge e) { deba@2338: return (e.id & 1) == 1; deba@2338: } deba@2338: deba@2338: static Edge direct(UEdge e, bool d) { deba@2338: return Edge(e.id * 2 + (d ? 1 : 0)); deba@2338: } deba@2338: deba@2338: void first(Node& node) const { deba@2338: node.id = first_node; deba@2338: } deba@2338: deba@2338: void next(Node& node) const { deba@2338: node.id = nodes[node.id].next; deba@2338: } deba@2338: deba@2338: void first(Edge& e) const { deba@2338: int n = first_node; deba@2338: while (n != -1 && nodes[n].first_out == -1) { deba@2338: n = nodes[n].next; deba@2338: } deba@2338: e.id = (n == -1) ? -1 : nodes[n].first_out; deba@2338: } deba@2338: deba@2338: void next(Edge& e) const { deba@2338: if (edges[e.id].next_out != -1) { deba@2338: e.id = edges[e.id].next_out; deba@2338: } else { deba@2338: int n = nodes[edges[e.id ^ 1].target].next; deba@2338: while(n != -1 && nodes[n].first_out == -1) { deba@2338: n = nodes[n].next; deba@2338: } deba@2338: e.id = (n == -1) ? -1 : nodes[n].first_out; deba@2338: } deba@2338: } deba@2338: deba@2338: void first(UEdge& e) const { deba@2338: int n = first_node; deba@2338: while (n != -1) { deba@2338: e.id = nodes[n].first_out; deba@2338: while ((e.id & 1) != 1) { deba@2338: e.id = edges[e.id].next_out; deba@2338: } deba@2338: if (e.id != -1) { deba@2338: e.id /= 2; deba@2338: return; deba@2338: } deba@2338: n = nodes[n].next; deba@2338: } deba@2338: e.id = -1; deba@2338: } deba@2338: deba@2338: void next(UEdge& e) const { deba@2338: int n = edges[e.id * 2].target; deba@2338: e.id = edges[(e.id * 2) | 1].next_out; deba@2338: while ((e.id & 1) != 1) { deba@2338: e.id = edges[e.id].next_out; deba@2338: } deba@2338: if (e.id != -1) { deba@2338: e.id /= 2; deba@2338: return; deba@2338: } deba@2338: n = nodes[n].next; deba@2338: while (n != -1) { deba@2338: e.id = nodes[n].first_out; deba@2338: while ((e.id & 1) != 1) { deba@2338: e.id = edges[e.id].next_out; deba@2338: } deba@2338: if (e.id != -1) { deba@2338: e.id /= 2; deba@2338: return; deba@2338: } deba@2338: n = nodes[n].next; deba@2338: } deba@2338: e.id = -1; deba@2338: } deba@2338: deba@2338: void firstOut(Edge &e, const Node& v) const { deba@2338: e.id = nodes[v.id].first_out; deba@2338: } deba@2338: void nextOut(Edge &e) const { deba@2338: e.id = edges[e.id].next_out; deba@2338: } deba@2338: deba@2338: void firstIn(Edge &e, const Node& v) const { deba@2338: e.id = ((nodes[v.id].first_out) ^ 1); deba@2338: if (e.id == -2) e.id = -1; deba@2338: } deba@2338: void nextIn(Edge &e) const { deba@2338: e.id = ((edges[e.id ^ 1].next_out) ^ 1); deba@2338: if (e.id == -2) e.id = -1; deba@2338: } deba@2338: deba@2338: void firstInc(UEdge &e, bool& d, const Node& v) const { deba@2338: int de = nodes[v.id].first_out; deba@2381: if (de != -1 ) { deba@2381: e.id = de / 2; deba@2381: d = ((de & 1) == 1); deba@2381: } else { deba@2381: e.id = -1; deba@2381: d = true; deba@2381: } deba@2338: } deba@2338: void nextInc(UEdge &e, bool& d) const { deba@2338: int de = (edges[(e.id * 2) | (d ? 1 : 0)].next_out); deba@2381: if (de != -1 ) { deba@2381: e.id = de / 2; deba@2381: d = ((de & 1) == 1); deba@2381: } else { deba@2381: e.id = -1; deba@2381: d = true; deba@2381: } deba@2338: } deba@2338: deba@2338: static int id(Node v) { return v.id; } deba@2338: static int id(Edge e) { return e.id; } deba@2338: static int id(UEdge e) { return e.id; } deba@2338: deba@2338: static Node nodeFromId(int id) { return Node(id);} deba@2338: static Edge edgeFromId(int id) { return Edge(id);} deba@2338: static UEdge uEdgeFromId(int id) { return UEdge(id);} deba@2338: deba@2338: Node addNode() { deba@2338: int n; deba@2338: deba@2338: if(first_free_node==-1) { deba@2338: n = nodes.size(); deba@2338: nodes.push_back(NodeT()); deba@2338: } else { deba@2338: n = first_free_node; deba@2338: first_free_node = nodes[n].next; deba@2338: } deba@2338: deba@2338: nodes[n].next = first_node; deba@2338: if (first_node != -1) nodes[first_node].prev = n; deba@2338: first_node = n; deba@2338: nodes[n].prev = -1; deba@2338: deba@2338: nodes[n].first_out = -1; deba@2338: deba@2338: return Node(n); deba@2338: } deba@2338: deba@2338: UEdge addEdge(Node u, Node v) { deba@2338: int n; deba@2338: deba@2338: if (first_free_edge == -1) { deba@2338: n = edges.size(); deba@2338: edges.push_back(EdgeT()); deba@2338: edges.push_back(EdgeT()); deba@2338: } else { deba@2338: n = first_free_edge; deba@2338: first_free_edge = edges[n].next_out; deba@2338: } deba@2338: deba@2338: edges[n].target = u.id; deba@2338: edges[n | 1].target = v.id; deba@2338: deba@2338: edges[n].next_out = nodes[v.id].first_out; deba@2338: if (nodes[v.id].first_out != -1) { deba@2338: edges[nodes[v.id].first_out].prev_out = n; deba@2498: } deba@2498: edges[n].prev_out = -1; deba@2498: nodes[v.id].first_out = n; deba@2498: deba@2498: edges[n | 1].next_out = nodes[u.id].first_out; deba@2338: if (nodes[u.id].first_out != -1) { deba@2338: edges[nodes[u.id].first_out].prev_out = (n | 1); deba@2338: } deba@2498: edges[n | 1].prev_out = -1; deba@2338: nodes[u.id].first_out = (n | 1); deba@2338: deba@2338: return UEdge(n / 2); deba@2338: } deba@2338: deba@2338: void erase(const Node& node) { deba@2338: int n = node.id; deba@2338: deba@2338: if(nodes[n].next != -1) { deba@2338: nodes[nodes[n].next].prev = nodes[n].prev; deba@2338: } deba@2338: deba@2338: if(nodes[n].prev != -1) { deba@2338: nodes[nodes[n].prev].next = nodes[n].next; deba@2338: } else { deba@2338: first_node = nodes[n].next; deba@2338: } deba@2338: deba@2338: nodes[n].next = first_free_node; deba@2338: first_free_node = n; deba@2338: deba@2338: } deba@2338: deba@2338: void erase(const UEdge& edge) { deba@2338: int n = edge.id * 2; deba@2338: deba@2338: if (edges[n].next_out != -1) { deba@2338: edges[edges[n].next_out].prev_out = edges[n].prev_out; deba@2338: } deba@2338: deba@2338: if (edges[n].prev_out != -1) { deba@2338: edges[edges[n].prev_out].next_out = edges[n].next_out; deba@2338: } else { deba@2338: nodes[edges[n | 1].target].first_out = edges[n].next_out; deba@2338: } deba@2338: deba@2338: if (edges[n | 1].next_out != -1) { deba@2338: edges[edges[n | 1].next_out].prev_out = edges[n | 1].prev_out; deba@2338: } deba@2338: deba@2338: if (edges[n | 1].prev_out != -1) { deba@2338: edges[edges[n | 1].prev_out].next_out = edges[n | 1].next_out; deba@2338: } else { deba@2338: nodes[edges[n].target].first_out = edges[n | 1].next_out; deba@2338: } deba@2338: deba@2338: edges[n].next_out = first_free_edge; deba@2338: first_free_edge = n; deba@2338: deba@2338: } deba@2338: deba@2338: void clear() { deba@2338: edges.clear(); deba@2338: nodes.clear(); deba@2338: first_node = first_free_node = first_free_edge = -1; deba@2338: } deba@2338: deba@2338: protected: deba@2338: deba@2338: void changeTarget(UEdge e, Node n) { deba@2338: if(edges[2 * e.id].next_out != -1) { deba@2338: edges[edges[2 * e.id].next_out].prev_out = edges[2 * e.id].prev_out; deba@2338: } deba@2338: if(edges[2 * e.id].prev_out != -1) { deba@2338: edges[edges[2 * e.id].prev_out].next_out = deba@2338: edges[2 * e.id].next_out; deba@2338: } else { deba@2338: nodes[edges[(2 * e.id) | 1].target].first_out = deba@2338: edges[2 * e.id].next_out; deba@2338: } deba@2338: deba@2338: if (nodes[n.id].first_out != -1) { deba@2338: edges[nodes[n.id].first_out].prev_out = 2 * e.id; deba@2338: } deba@2338: edges[(2 * e.id) | 1].target = n.id; deba@2338: edges[2 * e.id].prev_out = -1; deba@2338: edges[2 * e.id].next_out = nodes[n.id].first_out; deba@2338: nodes[n.id].first_out = 2 * e.id; deba@2338: } deba@2338: deba@2338: void changeSource(UEdge e, Node n) { deba@2338: if(edges[(2 * e.id) | 1].next_out != -1) { deba@2338: edges[edges[(2 * e.id) | 1].next_out].prev_out = deba@2338: edges[(2 * e.id) | 1].prev_out; deba@2338: } deba@2338: if(edges[(2 * e.id) | 1].prev_out != -1) { deba@2338: edges[edges[(2 * e.id) | 1].prev_out].next_out = deba@2338: edges[(2 * e.id) | 1].next_out; deba@2338: } else { deba@2338: nodes[edges[2 * e.id].target].first_out = deba@2338: edges[(2 * e.id) | 1].next_out; deba@2338: } deba@2338: deba@2338: if (nodes[n.id].first_out != -1) { deba@2338: edges[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); deba@2338: } deba@2338: edges[2 * e.id].target = n.id; deba@2338: edges[(2 * e.id) | 1].prev_out = -1; deba@2338: edges[(2 * e.id) | 1].next_out = nodes[n.id].first_out; deba@2338: nodes[n.id].first_out = ((2 * e.id) | 1); deba@2338: } deba@2338: deba@2338: }; deba@2338: deba@2338: // typedef UGraphExtender > deba@2338: // ExtendedListUGraphBase; deba@2338: deba@2338: typedef UGraphExtender ExtendedListUGraphBase; deba@2338: deba@2338: deba@2116: deba@2116: /// \addtogroup graphs deba@2116: /// @{ deba@2116: deba@2116: ///An undirected list graph class. deba@2116: alpar@2117: ///This is a simple and fast undirected graph implementation. deba@2116: /// alpar@2256: ///An important extra feature of this graph implementation is that alpar@2260: ///its maps are real \ref concepts::ReferenceMap "reference map"s. alpar@2256: /// deba@2116: ///It conforms to the alpar@2260: ///\ref concepts::UGraph "UGraph concept". deba@2116: /// alpar@2260: ///\sa concepts::UGraph. deba@2116: /// deba@2116: class ListUGraph : public ExtendedListUGraphBase { alpar@2128: private: alpar@2128: ///ListUGraph is \e not copy constructible. Use UGraphCopy() instead. alpar@2128: alpar@2128: ///ListUGraph is \e not copy constructible. Use UGraphCopy() instead. alpar@2128: /// alpar@2128: ListUGraph(const ListUGraph &) :ExtendedListUGraphBase() {}; alpar@2132: ///\brief Assignment of ListUGraph to another one is \e not allowed. alpar@2128: ///Use UGraphCopy() instead. alpar@2128: alpar@2132: ///Assignment of ListUGraph to another one is \e not allowed. alpar@2128: ///Use UGraphCopy() instead. alpar@2128: void operator=(const ListUGraph &) {} deba@2116: public: alpar@2128: /// Constructor alpar@2128: alpar@2128: /// Constructor. alpar@2128: /// alpar@2128: ListUGraph() {} alpar@2128: deba@2116: typedef ExtendedListUGraphBase Parent; deba@2338: deba@2338: typedef Parent::OutEdgeIt IncEdgeIt; deba@2338: deba@2116: /// \brief Add a new node to the graph. deba@2116: /// deba@2116: /// \return the new node. deba@2116: /// deba@2116: Node addNode() { return Parent::addNode(); } deba@2116: deba@2116: /// \brief Add a new edge to the graph. deba@2116: /// deba@2116: /// Add a new edge to the graph with source node \c s deba@2116: /// and target node \c t. deba@2116: /// \return the new undirected edge. deba@2116: UEdge addEdge(const Node& s, const Node& t) { deba@2116: return Parent::addEdge(s, t); deba@2116: } deba@2160: /// \brief Changes the source of \c e to \c n deba@2160: /// deba@2160: /// Changes the source of \c e to \c n deba@2160: /// deba@2160: ///\note The EdgeIts and InEdgeIts deba@2160: ///referencing the changed edge remain deba@2160: ///valid. However OutEdgeIts are invalidated. deba@2160: void changeSource(UEdge e, Node n) { deba@2160: Parent::changeSource(e,n); deba@2160: } deba@2116: /// \brief Changes the target of \c e to \c n deba@2116: /// deba@2116: /// Changes the target of \c e to \c n deba@2116: /// deba@2160: /// \note The EdgeIts referencing the changed edge remain deba@2160: /// valid. However the other iterators may be invalidated. deba@2116: void changeTarget(UEdge e, Node n) { deba@2116: Parent::changeTarget(e,n); deba@2116: } deba@2160: /// \brief Changes the source of \c e to \c n deba@2116: /// deba@2160: /// Changes the source of \c e to \c n. It changes the proper deba@2160: /// node of the represented undirected edge. deba@2116: /// deba@2160: ///\note The EdgeIts and InEdgeIts deba@2116: ///referencing the changed edge remain deba@2160: ///valid. However OutEdgeIts are invalidated. deba@2160: void changeSource(Edge e, Node n) { deba@2160: if (Parent::direction(e)) { deba@2160: Parent::changeSource(e,n); deba@2160: } else { deba@2160: Parent::changeTarget(e,n); deba@2160: } deba@2160: } deba@2160: /// \brief Changes the target of \c e to \c n deba@2160: /// deba@2160: /// Changes the target of \c e to \c n. It changes the proper deba@2160: /// node of the represented undirected edge. deba@2160: /// deba@2160: ///\note The EdgeIts and OutEdgeIts deba@2160: ///referencing the changed edge remain deba@2160: ///valid. However InEdgeIts are invalidated. deba@2160: void changeTarget(Edge e, Node n) { deba@2160: if (Parent::direction(e)) { deba@2160: Parent::changeTarget(e,n); deba@2160: } else { deba@2160: Parent::changeSource(e,n); deba@2160: } deba@2116: } deba@2116: /// \brief Contract two nodes. deba@2116: /// deba@2116: /// This function contracts two nodes. deba@2116: /// deba@2116: /// Node \p b will be removed but instead of deleting deba@2116: /// its neighboring edges, they will be joined to \p a. deba@2116: /// The last parameter \p r controls whether to remove loops. \c true deba@2116: /// means that loops will be removed. deba@2116: /// deba@2160: /// \note The EdgeIts referencing a moved edge remain deba@2116: /// valid. deba@2116: void contract(Node a, Node b, bool r = true) { deba@2116: for(IncEdgeIt e(*this, b); e!=INVALID;) { deba@2116: IncEdgeIt f = e; ++f; deba@2116: if (r && runningNode(e) == a) { deba@2116: erase(e); deba@2116: } else if (source(e) == b) { deba@2116: changeSource(e, a); deba@2116: } else { deba@2116: changeTarget(e, a); deba@2116: } deba@2116: e = f; deba@2116: } deba@2116: erase(b); deba@2116: } deba@2189: deba@2189: deba@2189: /// \brief Class to make a snapshot of the graph and restore deba@2189: /// to it later. deba@2189: /// deba@2189: /// Class to make a snapshot of the graph and to restore it deba@2189: /// later. deba@2189: /// deba@2189: /// The newly added nodes and undirected edges can be removed deba@2189: /// using the restore() function. deba@2189: /// deba@2189: /// \warning Edge and node deletions cannot be restored. This deba@2189: /// events invalidate the snapshot. deba@2189: class Snapshot { deba@2189: protected: deba@2189: deba@2189: typedef Parent::NodeNotifier NodeNotifier; deba@2189: deba@2189: class NodeObserverProxy : public NodeNotifier::ObserverBase { deba@2189: public: deba@2189: deba@2189: NodeObserverProxy(Snapshot& _snapshot) deba@2189: : snapshot(_snapshot) {} deba@2189: deba@2189: using NodeNotifier::ObserverBase::attach; deba@2189: using NodeNotifier::ObserverBase::detach; deba@2189: using NodeNotifier::ObserverBase::attached; deba@2189: deba@2189: protected: deba@2189: deba@2189: virtual void add(const Node& node) { deba@2189: snapshot.addNode(node); deba@2189: } deba@2189: virtual void add(const std::vector& nodes) { deba@2189: for (int i = nodes.size() - 1; i >= 0; ++i) { deba@2189: snapshot.addNode(nodes[i]); deba@2189: } deba@2189: } deba@2189: virtual void erase(const Node& node) { deba@2189: snapshot.eraseNode(node); deba@2189: } deba@2189: virtual void erase(const std::vector& nodes) { deba@2386: for (int i = 0; i < int(nodes.size()); ++i) { deba@2189: snapshot.eraseNode(nodes[i]); deba@2189: } deba@2189: } deba@2189: virtual void build() { deba@2189: Node node; deba@2189: std::vector nodes; deba@2386: for (notifier()->first(node); node != INVALID; deba@2386: notifier()->next(node)) { deba@2189: nodes.push_back(node); deba@2189: } deba@2189: for (int i = nodes.size() - 1; i >= 0; --i) { deba@2189: snapshot.addNode(nodes[i]); deba@2189: } deba@2189: } deba@2189: virtual void clear() { deba@2189: Node node; deba@2386: for (notifier()->first(node); node != INVALID; deba@2386: notifier()->next(node)) { deba@2189: snapshot.eraseNode(node); deba@2189: } deba@2189: } deba@2189: deba@2189: Snapshot& snapshot; deba@2189: }; deba@2189: deba@2189: class UEdgeObserverProxy : public UEdgeNotifier::ObserverBase { deba@2189: public: deba@2189: deba@2189: UEdgeObserverProxy(Snapshot& _snapshot) deba@2189: : snapshot(_snapshot) {} deba@2189: deba@2189: using UEdgeNotifier::ObserverBase::attach; deba@2189: using UEdgeNotifier::ObserverBase::detach; deba@2189: using UEdgeNotifier::ObserverBase::attached; deba@2189: deba@2189: protected: deba@2189: deba@2189: virtual void add(const UEdge& edge) { deba@2189: snapshot.addUEdge(edge); deba@2189: } deba@2189: virtual void add(const std::vector& edges) { deba@2189: for (int i = edges.size() - 1; i >= 0; ++i) { deba@2189: snapshot.addUEdge(edges[i]); deba@2189: } deba@2189: } deba@2189: virtual void erase(const UEdge& edge) { deba@2189: snapshot.eraseUEdge(edge); deba@2189: } deba@2189: virtual void erase(const std::vector& edges) { deba@2386: for (int i = 0; i < int(edges.size()); ++i) { deba@2189: snapshot.eraseUEdge(edges[i]); deba@2189: } deba@2189: } deba@2189: virtual void build() { deba@2189: UEdge edge; deba@2189: std::vector edges; deba@2386: for (notifier()->first(edge); edge != INVALID; deba@2386: notifier()->next(edge)) { deba@2189: edges.push_back(edge); deba@2189: } deba@2189: for (int i = edges.size() - 1; i >= 0; --i) { deba@2189: snapshot.addUEdge(edges[i]); deba@2189: } deba@2189: } deba@2189: virtual void clear() { deba@2189: UEdge edge; deba@2386: for (notifier()->first(edge); edge != INVALID; deba@2386: notifier()->next(edge)) { deba@2189: snapshot.eraseUEdge(edge); deba@2189: } deba@2189: } deba@2189: deba@2189: Snapshot& snapshot; deba@2189: }; deba@2189: deba@2189: ListUGraph *graph; deba@2189: deba@2189: NodeObserverProxy node_observer_proxy; deba@2189: UEdgeObserverProxy edge_observer_proxy; deba@2189: deba@2189: std::list added_nodes; deba@2189: std::list added_edges; deba@2189: deba@2189: deba@2189: void addNode(const Node& node) { deba@2189: added_nodes.push_front(node); deba@2189: } deba@2189: void eraseNode(const Node& node) { deba@2189: std::list::iterator it = deba@2189: std::find(added_nodes.begin(), added_nodes.end(), node); deba@2189: if (it == added_nodes.end()) { deba@2189: clear(); deba@2189: edge_observer_proxy.detach(); deba@2189: throw NodeNotifier::ImmediateDetach(); deba@2189: } else { deba@2189: added_nodes.erase(it); deba@2189: } deba@2189: } deba@2189: deba@2189: void addUEdge(const UEdge& edge) { deba@2189: added_edges.push_front(edge); deba@2189: } deba@2189: void eraseUEdge(const UEdge& edge) { deba@2189: std::list::iterator it = deba@2189: std::find(added_edges.begin(), added_edges.end(), edge); deba@2189: if (it == added_edges.end()) { deba@2189: clear(); deba@2189: node_observer_proxy.detach(); deba@2189: throw UEdgeNotifier::ImmediateDetach(); deba@2189: } else { deba@2189: added_edges.erase(it); deba@2189: } deba@2189: } deba@2189: deba@2189: void attach(ListUGraph &_graph) { deba@2189: graph = &_graph; deba@2381: node_observer_proxy.attach(graph->notifier(Node())); deba@2381: edge_observer_proxy.attach(graph->notifier(UEdge())); deba@2189: } deba@2189: deba@2189: void detach() { deba@2189: node_observer_proxy.detach(); deba@2189: edge_observer_proxy.detach(); deba@2189: } deba@2189: deba@2189: bool attached() const { deba@2189: return node_observer_proxy.attached(); deba@2189: } deba@2189: deba@2189: void clear() { deba@2189: added_nodes.clear(); deba@2189: added_edges.clear(); deba@2189: } deba@2189: deba@2189: public: deba@2189: deba@2189: /// \brief Default constructor. deba@2189: /// deba@2189: /// Default constructor. deba@2189: /// To actually make a snapshot you must call save(). deba@2189: Snapshot() deba@2189: : graph(0), node_observer_proxy(*this), deba@2189: edge_observer_proxy(*this) {} deba@2189: deba@2189: /// \brief Constructor that immediately makes a snapshot. deba@2189: /// deba@2189: /// This constructor immediately makes a snapshot of the graph. deba@2189: /// \param _graph The graph we make a snapshot of. deba@2189: Snapshot(ListUGraph &_graph) deba@2189: : node_observer_proxy(*this), deba@2189: edge_observer_proxy(*this) { deba@2189: attach(_graph); deba@2189: } deba@2189: deba@2189: /// \brief Make a snapshot. deba@2189: /// deba@2189: /// Make a snapshot of the graph. deba@2189: /// deba@2189: /// This function can be called more than once. In case of a repeated deba@2189: /// call, the previous snapshot gets lost. deba@2189: /// \param _graph The graph we make the snapshot of. deba@2189: void save(ListUGraph &_graph) { deba@2189: if (attached()) { deba@2189: detach(); deba@2189: clear(); deba@2189: } deba@2189: attach(_graph); deba@2189: } deba@2189: deba@2189: /// \brief Undo the changes until the last snapshot. deba@2189: // deba@2189: /// Undo the changes until the last snapshot created by save(). deba@2189: void restore() { deba@2189: detach(); deba@2189: for(std::list::iterator it = added_edges.begin(); deba@2189: it != added_edges.end(); ++it) { deba@2189: graph->erase(*it); deba@2189: } deba@2189: for(std::list::iterator it = added_nodes.begin(); deba@2189: it != added_nodes.end(); ++it) { deba@2189: graph->erase(*it); deba@2189: } deba@2189: clear(); deba@2189: } deba@2189: deba@2189: /// \brief Gives back true when the snapshot is valid. deba@2189: /// deba@2189: /// Gives back true when the snapshot is valid. deba@2189: bool valid() const { deba@2189: return attached(); deba@2189: } deba@2189: }; deba@2116: }; deba@2116: deba@2116: deba@2116: class ListBpUGraphBase { deba@2116: public: deba@2116: deba@2116: class NodeSetError : public LogicError { deba@2160: public: alpar@2151: virtual const char* what() const throw() { deba@2116: return "lemon::ListBpUGraph::NodeSetError"; deba@2116: } deba@2116: }; deba@2116: deba@2116: protected: deba@2116: deba@2116: struct NodeT { deba@2116: int first_edge, prev, next; deba@2116: }; deba@2116: deba@2116: struct UEdgeT { deba@2116: int aNode, prev_out, next_out; deba@2116: int bNode, prev_in, next_in; deba@2116: }; deba@2116: deba@2116: std::vector aNodes; deba@2116: std::vector bNodes; deba@2116: deba@2116: std::vector edges; deba@2116: deba@2116: int first_anode; deba@2116: int first_free_anode; deba@2116: deba@2116: int first_bnode; deba@2116: int first_free_bnode; deba@2116: deba@2116: int first_free_edge; deba@2116: deba@2116: public: deba@2116: deba@2116: class Node { deba@2116: friend class ListBpUGraphBase; deba@2116: protected: deba@2116: int id; deba@2116: deba@2116: explicit Node(int _id) : id(_id) {} deba@2116: public: deba@2116: Node() {} deba@2116: Node(Invalid) { id = -1; } deba@2116: bool operator==(const Node i) const {return id==i.id;} deba@2116: bool operator!=(const Node i) const {return id!=i.id;} deba@2116: bool operator<(const Node i) const {return id> 1].next; deba@2116: } deba@2116: deba@2116: void firstBNode(Node& node) const { deba@2116: node.id = first_bnode != -1 ? (first_bnode << 1) + 1 : -1; deba@2116: } deba@2116: void nextBNode(Node& node) const { deba@2116: node.id = bNodes[node.id >> 1].next; deba@2116: } deba@2116: deba@2116: void first(Node& node) const { deba@2116: if (first_anode != -1) { deba@2116: node.id = (first_anode << 1); deba@2116: } else if (first_bnode != -1) { deba@2116: node.id = (first_bnode << 1) + 1; deba@2116: } else { deba@2116: node.id = -1; deba@2116: } deba@2116: } deba@2116: void next(Node& node) const { deba@2116: if (aNode(node)) { deba@2116: node.id = aNodes[node.id >> 1].next; deba@2116: if (node.id == -1) { deba@2116: if (first_bnode != -1) { deba@2116: node.id = (first_bnode << 1) + 1; deba@2116: } deba@2116: } deba@2116: } else { deba@2116: node.id = bNodes[node.id >> 1].next; deba@2116: } deba@2116: } deba@2116: deba@2116: void first(UEdge& edge) const { deba@2386: int aid = first_anode; deba@2386: while (aid != -1 && aNodes[aid].first_edge == -1) { deba@2386: aid = aNodes[aid].next != -1 ? deba@2386: aNodes[aid].next >> 1 : -1; deba@2116: } deba@2386: if (aid != -1) { deba@2386: edge.id = aNodes[aid].first_edge; deba@2116: } else { deba@2116: edge.id = -1; deba@2116: } deba@2116: } deba@2116: void next(UEdge& edge) const { deba@2386: int aid = edges[edge.id].aNode >> 1; deba@2116: edge.id = edges[edge.id].next_out; deba@2116: if (edge.id == -1) { deba@2386: aid = aNodes[aid].next != -1 ? deba@2386: aNodes[aid].next >> 1 : -1; deba@2386: while (aid != -1 && aNodes[aid].first_edge == -1) { deba@2386: aid = aNodes[aid].next != -1 ? deba@2386: aNodes[aid].next >> 1 : -1; deba@2116: } deba@2386: if (aid != -1) { deba@2386: edge.id = aNodes[aid].first_edge; deba@2116: } else { deba@2116: edge.id = -1; deba@2116: } deba@2116: } deba@2116: } deba@2116: deba@2116: void firstFromANode(UEdge& edge, const Node& node) const { deba@2116: LEMON_ASSERT((node.id & 1) == 0, NodeSetError()); deba@2116: edge.id = aNodes[node.id >> 1].first_edge; deba@2116: } deba@2116: void nextFromANode(UEdge& edge) const { deba@2116: edge.id = edges[edge.id].next_out; deba@2116: } deba@2116: deba@2116: void firstFromBNode(UEdge& edge, const Node& node) const { deba@2116: LEMON_ASSERT((node.id & 1) == 1, NodeSetError()); deba@2116: edge.id = bNodes[node.id >> 1].first_edge; deba@2116: } deba@2116: void nextFromBNode(UEdge& edge) const { deba@2116: edge.id = edges[edge.id].next_in; deba@2116: } deba@2116: deba@2116: static int id(const Node& node) { deba@2116: return node.id; deba@2116: } deba@2116: static Node nodeFromId(int id) { deba@2116: return Node(id); deba@2116: } deba@2116: int maxNodeId() const { deba@2116: return aNodes.size() > bNodes.size() ? deba@2116: aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1; deba@2116: } deba@2116: deba@2116: static int id(const UEdge& edge) { deba@2116: return edge.id; deba@2116: } deba@2116: static UEdge uEdgeFromId(int id) { deba@2116: return UEdge(id); deba@2116: } deba@2116: int maxUEdgeId() const { deba@2116: return edges.size(); deba@2116: } deba@2116: deba@2116: static int aNodeId(const Node& node) { deba@2116: return node.id >> 1; deba@2116: } deba@2231: static Node nodeFromANodeId(int id) { deba@2116: return Node(id << 1); deba@2116: } deba@2116: int maxANodeId() const { deba@2116: return aNodes.size(); deba@2116: } deba@2116: deba@2116: static int bNodeId(const Node& node) { deba@2116: return node.id >> 1; deba@2116: } deba@2231: static Node nodeFromBNodeId(int id) { deba@2116: return Node((id << 1) + 1); deba@2116: } deba@2116: int maxBNodeId() const { deba@2116: return bNodes.size(); deba@2116: } deba@2116: deba@2116: Node aNode(const UEdge& edge) const { deba@2116: return Node(edges[edge.id].aNode); deba@2116: } deba@2116: Node bNode(const UEdge& edge) const { deba@2116: return Node(edges[edge.id].bNode); deba@2116: } deba@2116: deba@2116: static bool aNode(const Node& node) { deba@2116: return (node.id & 1) == 0; deba@2116: } deba@2116: deba@2116: static bool bNode(const Node& node) { deba@2116: return (node.id & 1) == 1; deba@2116: } deba@2116: deba@2116: Node addANode() { deba@2386: int aid; deba@2116: if (first_free_anode == -1) { deba@2386: aid = aNodes.size(); deba@2116: aNodes.push_back(NodeT()); deba@2116: } else { deba@2386: aid = first_free_anode; deba@2116: first_free_anode = aNodes[first_free_anode].next; deba@2116: } deba@2116: if (first_anode != -1) { deba@2386: aNodes[aid].next = first_anode << 1; deba@2386: aNodes[first_anode].prev = aid << 1; deba@2116: } else { deba@2386: aNodes[aid].next = -1; deba@2116: } deba@2386: aNodes[aid].prev = -1; deba@2386: first_anode = aid; deba@2386: aNodes[aid].first_edge = -1; deba@2386: return Node(aid << 1); deba@2116: } deba@2116: deba@2116: Node addBNode() { deba@2386: int bid; deba@2116: if (first_free_bnode == -1) { deba@2386: bid = bNodes.size(); deba@2116: bNodes.push_back(NodeT()); deba@2116: } else { deba@2386: bid = first_free_bnode; deba@2116: first_free_bnode = bNodes[first_free_bnode].next; deba@2116: } deba@2116: if (first_bnode != -1) { deba@2386: bNodes[bid].next = (first_bnode << 1) + 1; deba@2386: bNodes[first_bnode].prev = (bid << 1) + 1; deba@2116: } else { deba@2386: bNodes[bid].next = -1; deba@2116: } deba@2386: bNodes[bid].prev = -1; deba@2386: first_bnode = bid; deba@2386: bNodes[bid].first_edge = -1; deba@2386: return Node((bid << 1) + 1); deba@2116: } deba@2116: deba@2116: UEdge addEdge(const Node& source, const Node& target) { deba@2116: LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError()); deba@2116: int edgeId; deba@2116: if (first_free_edge != -1) { deba@2116: edgeId = first_free_edge; deba@2116: first_free_edge = edges[edgeId].next_out; deba@2116: } else { deba@2116: edgeId = edges.size(); deba@2116: edges.push_back(UEdgeT()); deba@2116: } deba@2116: if ((source.id & 1) == 0) { deba@2116: edges[edgeId].aNode = source.id; deba@2116: edges[edgeId].bNode = target.id; deba@2116: } else { deba@2116: edges[edgeId].aNode = target.id; deba@2116: edges[edgeId].bNode = source.id; deba@2116: } deba@2116: edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge; deba@2116: edges[edgeId].prev_out = -1; deba@2116: if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) { deba@2116: edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId; deba@2116: } deba@2116: aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId; deba@2116: edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge; deba@2116: edges[edgeId].prev_in = -1; deba@2116: if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) { deba@2116: edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId; deba@2116: } deba@2116: bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId; deba@2116: return UEdge(edgeId); deba@2116: } deba@2116: deba@2116: void erase(const Node& node) { deba@2116: if (aNode(node)) { deba@2386: int aid = node.id >> 1; deba@2386: if (aNodes[aid].prev != -1) { deba@2386: aNodes[aNodes[aid].prev >> 1].next = aNodes[aid].next; deba@2116: } else { deba@2189: first_anode = deba@2386: aNodes[aid].next != -1 ? aNodes[aid].next >> 1 : -1; deba@2116: } deba@2386: if (aNodes[aid].next != -1) { deba@2386: aNodes[aNodes[aid].next >> 1].prev = aNodes[aid].prev; deba@2116: } deba@2386: aNodes[aid].next = first_free_anode; deba@2386: first_free_anode = aid; deba@2116: } else { deba@2386: int bid = node.id >> 1; deba@2386: if (bNodes[bid].prev != -1) { deba@2386: bNodes[bNodes[bid].prev >> 1].next = bNodes[bid].next; deba@2116: } else { deba@2189: first_bnode = deba@2386: bNodes[bid].next != -1 ? bNodes[bid].next >> 1 : -1; deba@2116: } deba@2386: if (bNodes[bid].next != -1) { deba@2386: bNodes[bNodes[bid].next >> 1].prev = bNodes[bid].prev; deba@2116: } deba@2386: bNodes[bid].next = first_free_bnode; deba@2386: first_free_bnode = bid; deba@2116: } deba@2116: } deba@2116: deba@2116: void erase(const UEdge& edge) { deba@2116: deba@2116: if (edges[edge.id].prev_out != -1) { deba@2116: edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out; deba@2116: } else { deba@2116: aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out; deba@2116: } deba@2116: if (edges[edge.id].next_out != -1) { deba@2116: edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out; deba@2116: } deba@2116: deba@2116: if (edges[edge.id].prev_in != -1) { deba@2116: edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in; deba@2116: } else { deba@2116: bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in; deba@2116: } deba@2116: if (edges[edge.id].next_in != -1) { deba@2116: edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in; deba@2116: } deba@2116: deba@2116: edges[edge.id].next_out = first_free_edge; deba@2116: first_free_edge = edge.id; deba@2116: } alpar@2128: deba@2116: void clear() { deba@2116: aNodes.clear(); deba@2116: bNodes.clear(); deba@2116: edges.clear(); deba@2116: first_anode = -1; deba@2116: first_free_anode = -1; deba@2116: first_bnode = -1; deba@2116: first_free_bnode = -1; deba@2116: first_free_edge = -1; deba@2116: } deba@2116: deba@2160: void changeANode(const UEdge& edge, const Node& node) { deba@2160: LEMON_ASSERT((node.id & 1) == 0, NodeSetError()); deba@2160: if (edges[edge.id].prev_out != -1) { deba@2160: edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out; deba@2160: } else { deba@2160: aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out; deba@2160: } deba@2160: if (edges[edge.id].next_out != -1) { deba@2160: edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out; deba@2160: } deba@2160: if (aNodes[node.id >> 1].first_edge != -1) { deba@2160: edges[aNodes[node.id >> 1].first_edge].prev_out = edge.id; deba@2160: } deba@2160: edges[edge.id].prev_out = -1; deba@2160: edges[edge.id].next_out = aNodes[node.id >> 1].first_edge; deba@2160: aNodes[node.id >> 1].first_edge = edge.id; deba@2160: edges[edge.id].aNode = node.id; deba@2160: } deba@2160: deba@2160: void changeBNode(const UEdge& edge, const Node& node) { deba@2160: LEMON_ASSERT((node.id & 1) == 1, NodeSetError()); deba@2160: if (edges[edge.id].prev_in != -1) { deba@2160: edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in; deba@2160: } else { deba@2160: bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in; deba@2160: } deba@2160: if (edges[edge.id].next_in != -1) { deba@2160: edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in; deba@2160: } deba@2160: if (bNodes[node.id >> 1].first_edge != -1) { deba@2160: edges[bNodes[node.id >> 1].first_edge].prev_in = edge.id; deba@2160: } deba@2160: edges[edge.id].prev_in = -1; deba@2160: edges[edge.id].next_in = bNodes[node.id >> 1].first_edge; deba@2160: bNodes[node.id >> 1].first_edge = edge.id; deba@2160: edges[edge.id].bNode = node.id; deba@2160: } deba@2160: deba@2116: }; deba@2116: deba@2116: deba@2231: typedef BpUGraphExtender > deba@2231: ExtendedListBpUGraphBase; deba@2116: deba@2116: /// \ingroup graphs deba@2116: /// deba@2116: /// \brief A smart bipartite undirected graph class. deba@2116: /// deba@2116: /// This is a bipartite undirected graph implementation. alpar@2260: /// It is conforms to the \ref concepts::BpUGraph "BpUGraph concept". alpar@2256: /// alpar@2256: ///An important extra feature of this graph implementation is that alpar@2260: ///its maps are real \ref concepts::ReferenceMap "reference map"s. alpar@2256: /// alpar@2260: /// \sa concepts::BpUGraph. deba@2116: /// deba@2160: class ListBpUGraph : public ExtendedListBpUGraphBase { deba@2160: /// \brief ListBpUGraph is \e not copy constructible. deba@2160: /// deba@2160: ///ListBpUGraph is \e not copy constructible. deba@2160: ListBpUGraph(const ListBpUGraph &) :ExtendedListBpUGraphBase() {}; deba@2160: /// \brief Assignment of ListBpUGraph to another one is \e not deba@2160: /// allowed. deba@2160: /// deba@2160: /// Assignment of ListBpUGraph to another one is \e not allowed. deba@2160: void operator=(const ListBpUGraph &) {} deba@2160: public: deba@2160: /// \brief Constructor deba@2160: /// deba@2160: /// Constructor. deba@2160: /// deba@2160: ListBpUGraph() {} deba@2160: deba@2160: typedef ExtendedListBpUGraphBase Parent; deba@2160: /// \brief Add a new ANode to the graph. deba@2160: /// deba@2160: /// \return the new node. deba@2160: /// deba@2160: Node addANode() { return Parent::addANode(); } deba@2160: deba@2160: /// \brief Add a new BNode to the graph. deba@2160: /// deba@2160: /// \return the new node. deba@2160: /// deba@2160: Node addBNode() { return Parent::addBNode(); } deba@2160: deba@2160: /// \brief Add a new edge to the graph. deba@2160: /// deba@2160: /// Add a new edge to the graph with an ANode and a BNode. deba@2160: /// \return the new undirected edge. deba@2160: UEdge addEdge(const Node& s, const Node& t) { deba@2160: return Parent::addEdge(s, t); deba@2160: } deba@2160: deba@2160: /// \brief Changes the ANode of \c e to \c n deba@2160: /// deba@2160: /// Changes the ANode of \c e to \c n deba@2160: /// deba@2160: ///\note The EdgeIts and InEdgeIts referencing deba@2160: ///the changed edge remain valid. However OutEdgeIts are deba@2160: ///invalidated. deba@2160: void changeANode(UEdge e, Node n) { deba@2160: Parent::changeANode(e,n); deba@2160: } deba@2160: deba@2160: /// \brief Changes the BNode of \c e to \c n deba@2160: /// deba@2160: /// Changes the BNode of \c e to \c n deba@2160: /// deba@2160: /// \note The EdgeIts and OutEdgeIts deba@2160: /// referencing the changed edge remain deba@2160: /// valid. However InEdgeIts are invalidated. deba@2160: void changeBNode(UEdge e, Node n) { deba@2160: Parent::changeBNode(e,n); deba@2160: } deba@2160: deba@2160: /// \brief Changes the source(ANode) of \c e to \c n deba@2160: /// deba@2160: /// Changes the source(ANode) of \c e to \c n deba@2160: /// deba@2160: ///\note The EdgeIts and InEdgeIts referencing deba@2160: ///the changed edge remain valid. However OutEdgeIts are deba@2160: ///invalidated. deba@2160: void changeSource(UEdge e, Node n) { deba@2160: Parent::changeANode(e,n); deba@2160: } deba@2160: deba@2160: /// \brief Changes the target(BNode) of \c e to \c n deba@2160: /// deba@2160: /// Changes the target(BNode) of \c e to \c n deba@2160: /// deba@2160: /// \note The EdgeIts and OutEdgeIts deba@2160: /// referencing the changed edge remain deba@2160: /// valid. However InEdgeIts are invalidated. deba@2160: void changeTarget(UEdge e, Node n) { deba@2160: Parent::changeBNode(e,n); deba@2160: } deba@2160: deba@2160: /// \brief Changes the source of \c e to \c n deba@2160: /// deba@2160: /// Changes the source of \c e to \c n. It changes the proper deba@2160: /// node of the represented undirected edge. deba@2160: /// deba@2160: ///\note The EdgeIts and InEdgeIts deba@2160: ///referencing the changed edge remain deba@2160: ///valid. However OutEdgeIts are invalidated. deba@2160: void changeSource(Edge e, Node n) { deba@2160: if (Parent::direction(e)) { deba@2160: Parent::changeANode(e,n); deba@2160: } else { deba@2160: Parent::changeBNode(e,n); deba@2160: } deba@2160: } deba@2160: /// \brief Changes the target of \c e to \c n deba@2160: /// deba@2160: /// Changes the target of \c e to \c n. It changes the proper deba@2160: /// node of the represented undirected edge. deba@2160: /// deba@2160: ///\note The EdgeIts and OutEdgeIts deba@2160: ///referencing the changed edge remain deba@2160: ///valid. However InEdgeIts are invalidated. deba@2160: void changeTarget(Edge e, Node n) { deba@2160: if (Parent::direction(e)) { deba@2160: Parent::changeBNode(e,n); deba@2160: } else { deba@2160: Parent::changeANode(e,n); deba@2160: } deba@2160: } deba@2160: /// \brief Contract two nodes. deba@2160: /// deba@2160: /// This function contracts two nodes. deba@2160: /// deba@2160: /// Node \p b will be removed but instead of deleting its deba@2160: /// neighboring edges, they will be joined to \p a. The two nodes deba@2160: /// should be from the same nodeset, of course. deba@2160: /// deba@2160: /// \note The EdgeIts referencing a moved edge remain deba@2160: /// valid. deba@2160: void contract(const Node& a, const Node& b) { deba@2160: LEMON_ASSERT(Parent::aNode(a) == Parent::aNode(b), NodeSetError()); deba@2160: if (Parent::aNode(a)) { deba@2160: for (IncEdgeIt e(*this, b); e!=INVALID;) { deba@2160: IncEdgeIt f = e; ++f; deba@2160: changeSource(e, a); deba@2160: e = f; deba@2160: } deba@2160: } else { deba@2160: for (IncEdgeIt e(*this, b); e!=INVALID;) { deba@2160: IncEdgeIt f = e; ++f; deba@2160: changeTarget(e, a); deba@2160: e = f; deba@2160: } deba@2160: } deba@2160: erase(b); deba@2160: } deba@2160: deba@2189: /// \brief Class to make a snapshot of the graph and restore deba@2189: /// to it later. deba@2189: /// deba@2189: /// Class to make a snapshot of the graph and to restore it deba@2189: /// later. deba@2189: /// deba@2189: /// The newly added nodes and undirected edges can be removed deba@2189: /// using the restore() function. deba@2189: /// deba@2189: /// \warning Edge and node deletions cannot be restored. This deba@2189: /// events invalidate the snapshot. deba@2189: class Snapshot { deba@2189: protected: deba@2189: deba@2189: typedef Parent::NodeNotifier NodeNotifier; deba@2189: deba@2189: class NodeObserverProxy : public NodeNotifier::ObserverBase { deba@2189: public: deba@2189: deba@2189: NodeObserverProxy(Snapshot& _snapshot) deba@2189: : snapshot(_snapshot) {} deba@2189: deba@2189: using NodeNotifier::ObserverBase::attach; deba@2189: using NodeNotifier::ObserverBase::detach; deba@2189: using NodeNotifier::ObserverBase::attached; deba@2189: deba@2189: protected: deba@2189: deba@2189: virtual void add(const Node& node) { deba@2189: snapshot.addNode(node); deba@2189: } deba@2189: virtual void add(const std::vector& nodes) { deba@2189: for (int i = nodes.size() - 1; i >= 0; ++i) { deba@2189: snapshot.addNode(nodes[i]); deba@2189: } deba@2189: } deba@2189: virtual void erase(const Node& node) { deba@2189: snapshot.eraseNode(node); deba@2189: } deba@2189: virtual void erase(const std::vector& nodes) { deba@2386: for (int i = 0; i < int(nodes.size()); ++i) { deba@2189: snapshot.eraseNode(nodes[i]); deba@2189: } deba@2189: } deba@2189: virtual void build() { deba@2189: Node node; deba@2189: std::vector nodes; deba@2386: for (notifier()->first(node); node != INVALID; deba@2386: notifier()->next(node)) { deba@2189: nodes.push_back(node); deba@2189: } deba@2189: for (int i = nodes.size() - 1; i >= 0; --i) { deba@2189: snapshot.addNode(nodes[i]); deba@2189: } deba@2189: } deba@2189: virtual void clear() { deba@2189: Node node; deba@2386: for (notifier()->first(node); node != INVALID; deba@2386: notifier()->next(node)) { deba@2189: snapshot.eraseNode(node); deba@2189: } deba@2189: } deba@2189: deba@2189: Snapshot& snapshot; deba@2189: }; deba@2189: deba@2189: class UEdgeObserverProxy : public UEdgeNotifier::ObserverBase { deba@2189: public: deba@2189: deba@2189: UEdgeObserverProxy(Snapshot& _snapshot) deba@2189: : snapshot(_snapshot) {} deba@2189: deba@2189: using UEdgeNotifier::ObserverBase::attach; deba@2189: using UEdgeNotifier::ObserverBase::detach; deba@2189: using UEdgeNotifier::ObserverBase::attached; deba@2189: deba@2189: protected: deba@2189: deba@2189: virtual void add(const UEdge& edge) { deba@2189: snapshot.addUEdge(edge); deba@2189: } deba@2189: virtual void add(const std::vector& edges) { deba@2189: for (int i = edges.size() - 1; i >= 0; ++i) { deba@2189: snapshot.addUEdge(edges[i]); deba@2189: } deba@2189: } deba@2189: virtual void erase(const UEdge& edge) { deba@2189: snapshot.eraseUEdge(edge); deba@2189: } deba@2189: virtual void erase(const std::vector& edges) { deba@2386: for (int i = 0; i < int(edges.size()); ++i) { deba@2189: snapshot.eraseUEdge(edges[i]); deba@2189: } deba@2189: } deba@2189: virtual void build() { deba@2189: UEdge edge; deba@2189: std::vector edges; deba@2386: for (notifier()->first(edge); edge != INVALID; deba@2386: notifier()->next(edge)) { deba@2189: edges.push_back(edge); deba@2189: } deba@2189: for (int i = edges.size() - 1; i >= 0; --i) { deba@2189: snapshot.addUEdge(edges[i]); deba@2189: } deba@2189: } deba@2189: virtual void clear() { deba@2189: UEdge edge; deba@2386: for (notifier()->first(edge); edge != INVALID; deba@2386: notifier()->next(edge)) { deba@2189: snapshot.eraseUEdge(edge); deba@2189: } deba@2189: } deba@2189: deba@2189: Snapshot& snapshot; deba@2189: }; deba@2189: deba@2189: ListBpUGraph *graph; deba@2189: deba@2189: NodeObserverProxy node_observer_proxy; deba@2189: UEdgeObserverProxy edge_observer_proxy; deba@2189: deba@2189: std::list added_nodes; deba@2189: std::list added_edges; deba@2189: deba@2189: deba@2189: void addNode(const Node& node) { deba@2189: added_nodes.push_front(node); deba@2189: } deba@2189: void eraseNode(const Node& node) { deba@2189: std::list::iterator it = deba@2189: std::find(added_nodes.begin(), added_nodes.end(), node); deba@2189: if (it == added_nodes.end()) { deba@2189: clear(); deba@2189: edge_observer_proxy.detach(); deba@2189: throw NodeNotifier::ImmediateDetach(); deba@2189: } else { deba@2189: added_nodes.erase(it); deba@2189: } deba@2189: } deba@2189: deba@2189: void addUEdge(const UEdge& edge) { deba@2189: added_edges.push_front(edge); deba@2189: } deba@2189: void eraseUEdge(const UEdge& edge) { deba@2189: std::list::iterator it = deba@2189: std::find(added_edges.begin(), added_edges.end(), edge); deba@2189: if (it == added_edges.end()) { deba@2189: clear(); deba@2189: node_observer_proxy.detach(); deba@2189: throw UEdgeNotifier::ImmediateDetach(); deba@2189: } else { deba@2189: added_edges.erase(it); deba@2189: } deba@2189: } deba@2189: deba@2189: void attach(ListBpUGraph &_graph) { deba@2189: graph = &_graph; deba@2381: node_observer_proxy.attach(graph->notifier(Node())); deba@2381: edge_observer_proxy.attach(graph->notifier(UEdge())); deba@2189: } deba@2189: deba@2189: void detach() { deba@2189: node_observer_proxy.detach(); deba@2189: edge_observer_proxy.detach(); deba@2189: } deba@2189: deba@2189: bool attached() const { deba@2189: return node_observer_proxy.attached(); deba@2189: } deba@2189: deba@2189: void clear() { deba@2189: added_nodes.clear(); deba@2189: added_edges.clear(); deba@2189: } deba@2189: deba@2189: public: deba@2189: deba@2189: /// \brief Default constructor. deba@2189: /// deba@2189: /// Default constructor. deba@2189: /// To actually make a snapshot you must call save(). deba@2189: Snapshot() deba@2189: : graph(0), node_observer_proxy(*this), deba@2189: edge_observer_proxy(*this) {} deba@2189: deba@2189: /// \brief Constructor that immediately makes a snapshot. deba@2189: /// deba@2189: /// This constructor immediately makes a snapshot of the graph. deba@2189: /// \param _graph The graph we make a snapshot of. deba@2189: Snapshot(ListBpUGraph &_graph) deba@2189: : node_observer_proxy(*this), deba@2189: edge_observer_proxy(*this) { deba@2189: attach(_graph); deba@2189: } deba@2189: deba@2189: /// \brief Make a snapshot. deba@2189: /// deba@2189: /// Make a snapshot of the graph. deba@2189: /// deba@2189: /// This function can be called more than once. In case of a repeated deba@2189: /// call, the previous snapshot gets lost. deba@2189: /// \param _graph The graph we make the snapshot of. deba@2189: void save(ListBpUGraph &_graph) { deba@2189: if (attached()) { deba@2189: detach(); deba@2189: clear(); deba@2189: } deba@2189: attach(_graph); deba@2189: } deba@2189: deba@2189: /// \brief Undo the changes until the last snapshot. deba@2189: // deba@2189: /// Undo the changes until the last snapshot created by save(). deba@2189: void restore() { deba@2189: detach(); deba@2189: for(std::list::iterator it = added_edges.begin(); deba@2189: it != added_edges.end(); ++it) { deba@2189: graph->erase(*it); deba@2189: } deba@2189: for(std::list::iterator it = added_nodes.begin(); deba@2189: it != added_nodes.end(); ++it) { deba@2189: graph->erase(*it); deba@2189: } deba@2189: clear(); deba@2189: } deba@2189: deba@2189: /// \brief Gives back true when the snapshot is valid. deba@2189: /// deba@2189: /// Gives back true when the snapshot is valid. deba@2189: bool valid() const { deba@2189: return attached(); deba@2189: } deba@2189: }; deba@2160: }; deba@2116: deba@2116: deba@2116: /// @} alpar@948: } //namespace lemon klao@946: alpar@400: klao@946: #endif