alpar@209: /* -*- mode: C++; indent-tabs-mode: nil; -*- deba@109: * alpar@209: * This file is a part of LEMON, a generic C++ optimization library. deba@109: * alpar@1092: * Copyright (C) 2003-2013 deba@109: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@109: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@109: * deba@109: * Permission to use, modify and distribute this software is granted deba@109: * provided that this copyright notice appears in all copies. For deba@109: * precise terms see the accompanying LICENSE file. deba@109: * deba@109: * This software is provided "AS IS" with no warranty of any kind, deba@109: * express or implied, and with no claim as to its suitability for any deba@109: * purpose. deba@109: * deba@109: */ deba@109: deba@109: #ifndef LEMON_SMART_GRAPH_H deba@109: #define LEMON_SMART_GRAPH_H deba@109: deba@109: ///\ingroup graphs deba@109: ///\file deba@109: ///\brief SmartDigraph and SmartGraph classes. deba@109: deba@109: #include deba@109: deba@220: #include deba@109: #include deba@109: #include deba@109: deba@109: namespace lemon { deba@109: deba@109: class SmartDigraph; deba@109: deba@109: class SmartDigraphBase { deba@109: protected: deba@109: alpar@209: struct NodeT deba@109: { alpar@209: int first_in, first_out; deba@109: NodeT() {} deba@109: }; alpar@209: struct ArcT deba@109: { alpar@209: int target, source, next_in, next_out; alpar@209: ArcT() {} deba@109: }; deba@109: ggab90@1130: std::vector _nodes; ggab90@1130: std::vector _arcs; alpar@209: deba@109: public: deba@109: kpeter@617: typedef SmartDigraphBase Digraph; deba@109: deba@109: class Node; deba@109: class Arc; deba@109: deba@109: public: deba@109: ggab90@1130: SmartDigraphBase() : _nodes(), _arcs() { } alpar@209: SmartDigraphBase(const SmartDigraphBase &_g) ggab90@1130: : _nodes(_g._nodes), _arcs(_g._arcs) { } alpar@209: deba@109: typedef True NodeNumTag; kpeter@360: typedef True ArcNumTag; deba@109: ggab90@1130: int nodeNum() const { return _nodes.size(); } ggab90@1130: int arcNum() const { return _arcs.size(); } deba@109: ggab90@1130: int maxNodeId() const { return _nodes.size()-1; } ggab90@1130: int maxArcId() const { return _arcs.size()-1; } deba@109: deba@109: Node addNode() { ggab90@1130: int n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); ggab90@1130: _nodes[n].first_in = -1; ggab90@1130: _nodes[n].first_out = -1; deba@109: return Node(n); deba@109: } alpar@209: deba@109: Arc addArc(Node u, Node v) { ggab90@1130: int n = _arcs.size(); ggab90@1130: _arcs.push_back(ArcT()); ggab90@1130: _arcs[n].source = u._id; ggab90@1130: _arcs[n].target = v._id; ggab90@1130: _arcs[n].next_out = _nodes[u._id].first_out; ggab90@1130: _arcs[n].next_in = _nodes[v._id].first_in; ggab90@1130: _nodes[u._id].first_out = _nodes[v._id].first_in = n; deba@109: deba@109: return Arc(n); deba@109: } deba@109: deba@109: void clear() { ggab90@1130: _arcs.clear(); ggab90@1130: _nodes.clear(); deba@109: } deba@109: ggab90@1130: Node source(Arc a) const { return Node(_arcs[a._id].source); } ggab90@1130: Node target(Arc a) const { return Node(_arcs[a._id].target); } deba@109: deba@109: static int id(Node v) { return v._id; } deba@109: static int id(Arc a) { return a._id; } deba@109: deba@109: static Node nodeFromId(int id) { return Node(id);} deba@109: static Arc arcFromId(int id) { return Arc(id);} deba@109: alpar@209: bool valid(Node n) const { ggab90@1130: return n._id >= 0 && n._id < static_cast(_nodes.size()); deba@149: } alpar@209: bool valid(Arc a) const { ggab90@1130: return a._id >= 0 && a._id < static_cast(_arcs.size()); deba@149: } deba@149: deba@109: class Node { deba@109: friend class SmartDigraphBase; deba@109: friend class SmartDigraph; deba@109: deba@109: protected: deba@109: int _id; deba@109: explicit Node(int id) : _id(id) {} deba@109: public: deba@109: Node() {} deba@109: Node (Invalid) : _id(-1) {} deba@109: bool operator==(const Node i) const {return _id == i._id;} deba@109: bool operator!=(const Node i) const {return _id != i._id;} deba@109: bool operator<(const Node i) const {return _id < i._id;} deba@109: }; alpar@209: deba@109: deba@109: class Arc { deba@109: friend class SmartDigraphBase; deba@109: friend class SmartDigraph; deba@109: deba@109: protected: deba@109: int _id; deba@109: explicit Arc(int id) : _id(id) {} deba@109: public: deba@109: Arc() { } deba@109: Arc (Invalid) : _id(-1) {} deba@109: bool operator==(const Arc i) const {return _id == i._id;} deba@109: bool operator!=(const Arc i) const {return _id != i._id;} deba@109: bool operator<(const Arc i) const {return _id < i._id;} deba@109: }; deba@109: deba@109: void first(Node& node) const { ggab90@1130: node._id = _nodes.size() - 1; deba@109: } deba@109: deba@109: static void next(Node& node) { deba@109: --node._id; deba@109: } deba@109: deba@109: void first(Arc& arc) const { ggab90@1130: arc._id = _arcs.size() - 1; deba@109: } deba@109: deba@109: static void next(Arc& arc) { deba@109: --arc._id; deba@109: } deba@109: deba@109: void firstOut(Arc& arc, const Node& node) const { ggab90@1130: arc._id = _nodes[node._id].first_out; deba@109: } deba@109: deba@109: void nextOut(Arc& arc) const { ggab90@1130: arc._id = _arcs[arc._id].next_out; deba@109: } deba@109: deba@109: void firstIn(Arc& arc, const Node& node) const { ggab90@1130: arc._id = _nodes[node._id].first_in; deba@109: } alpar@209: deba@109: void nextIn(Arc& arc) const { ggab90@1130: arc._id = _arcs[arc._id].next_in; deba@109: } deba@109: deba@109: }; deba@109: deba@109: typedef DigraphExtender ExtendedSmartDigraphBase; deba@109: deba@109: ///\ingroup graphs deba@109: /// deba@109: ///\brief A smart directed graph class. deba@109: /// kpeter@735: ///\ref SmartDigraph is a simple and fast digraph implementation. kpeter@735: ///It is also quite memory efficient but at the price alpar@877: ///that it does not support node and arc deletion kpeter@735: ///(except for the Snapshot feature). deba@109: /// kpeter@735: ///This type fully conforms to the \ref concepts::Digraph "Digraph concept" kpeter@735: ///and it also provides some additional functionalities. kpeter@735: ///Most of its member functions and nested classes are documented kpeter@735: ///only in the concept class. kpeter@735: /// kpeter@787: ///This class provides constant time counting for nodes and arcs. kpeter@787: /// kpeter@735: ///\sa concepts::Digraph kpeter@735: ///\sa SmartGraph deba@109: class SmartDigraph : public ExtendedSmartDigraphBase { deba@109: typedef ExtendedSmartDigraphBase Parent; deba@109: deba@109: private: kpeter@735: /// Digraphs are \e not copy constructible. Use DigraphCopy instead. deba@109: SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {}; kpeter@735: /// \brief Assignment of a digraph to another one is \e not allowed. kpeter@735: /// Use DigraphCopy instead. deba@109: void operator=(const SmartDigraph &) {} deba@109: deba@109: public: alpar@209: deba@109: /// Constructor alpar@209: deba@109: /// Constructor. deba@109: /// deba@109: SmartDigraph() {}; alpar@209: deba@109: ///Add a new node to the digraph. alpar@209: kpeter@735: ///This function adds a new node to the digraph. kpeter@735: ///\return The new node. deba@109: Node addNode() { return Parent::addNode(); } alpar@209: deba@109: ///Add a new arc to the digraph. alpar@209: kpeter@735: ///This function adds a new arc to the digraph with source node \c s deba@109: ///and target node \c t. kpeter@559: ///\return The new arc. kpeter@735: Arc addArc(Node s, Node t) { alpar@209: return Parent::addArc(s, t); deba@109: } deba@109: deba@149: /// \brief Node validity check deba@149: /// kpeter@735: /// This function gives back \c true if the given node is valid, kpeter@735: /// i.e. it is a real node of the digraph. deba@149: /// deba@149: /// \warning A removed node (using Snapshot) could become valid again kpeter@735: /// if new nodes are added to the digraph. deba@149: bool valid(Node n) const { return Parent::valid(n); } deba@149: deba@149: /// \brief Arc validity check deba@149: /// kpeter@735: /// This function gives back \c true if the given arc is valid, kpeter@735: /// i.e. it is a real arc of the digraph. deba@149: /// deba@149: /// \warning A removed arc (using Snapshot) could become valid again kpeter@735: /// if new arcs are added to the graph. deba@149: bool valid(Arc a) const { return Parent::valid(a); } deba@149: deba@109: ///Split a node. alpar@209: kpeter@735: ///This function splits the given node. First, a new node is added kpeter@735: ///to the digraph, then the source of each outgoing arc of node \c n kpeter@735: ///is moved to this new node. kpeter@735: ///If the second parameter \c connect is \c true (this is the default kpeter@735: ///value), then a new arc from node \c n to the newly created node kpeter@735: ///is also added. deba@109: ///\return The newly created node. deba@109: /// kpeter@735: ///\note All iterators remain valid. kpeter@735: /// deba@109: ///\warning This functionality cannot be used together with the Snapshot deba@109: ///feature. deba@109: Node split(Node n, bool connect = true) deba@109: { deba@109: Node b = addNode(); ggab90@1130: _nodes[b._id].first_out=_nodes[n._id].first_out; ggab90@1130: _nodes[n._id].first_out=-1; ggab90@1130: for(int i=_nodes[b._id].first_out; i!=-1; i=_arcs[i].next_out) { ggab90@1130: _arcs[i].source=b._id; kpeter@370: } deba@109: if(connect) addArc(n,b); deba@109: return b; deba@109: } deba@109: kpeter@735: ///Clear the digraph. kpeter@735: kpeter@735: ///This function erases all nodes and arcs from the digraph. kpeter@735: /// kpeter@735: void clear() { kpeter@735: Parent::clear(); kpeter@735: } kpeter@735: kpeter@735: /// Reserve memory for nodes. kpeter@735: kpeter@735: /// Using this function, it is possible to avoid superfluous memory kpeter@735: /// allocation: if you know that the digraph you want to build will kpeter@735: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@735: /// then it is worth reserving space for this amount before starting kpeter@735: /// to build the digraph. kpeter@735: /// \sa reserveArc() ggab90@1130: void reserveNode(int n) { _nodes.reserve(n); }; kpeter@735: kpeter@735: /// Reserve memory for arcs. kpeter@735: kpeter@735: /// Using this function, it is possible to avoid superfluous memory kpeter@735: /// allocation: if you know that the digraph you want to build will kpeter@735: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@735: /// then it is worth reserving space for this amount before starting kpeter@735: /// to build the digraph. kpeter@735: /// \sa reserveNode() ggab90@1130: void reserveArc(int m) { _arcs.reserve(m); }; kpeter@735: deba@109: public: alpar@209: deba@109: class Snapshot; deba@109: deba@109: protected: deba@109: deba@109: void restoreSnapshot(const Snapshot &s) deba@109: { ggab90@1130: while(s.arc_num<_arcs.size()) { ggab90@1130: Arc arc = arcFromId(_arcs.size()-1); alpar@209: Parent::notifier(Arc()).erase(arc); ggab90@1130: _nodes[_arcs.back().source].first_out=_arcs.back().next_out; ggab90@1130: _nodes[_arcs.back().target].first_in=_arcs.back().next_in; ggab90@1130: _arcs.pop_back(); deba@109: } ggab90@1130: while(s.node_num<_nodes.size()) { ggab90@1130: Node node = nodeFromId(_nodes.size()-1); alpar@209: Parent::notifier(Node()).erase(node); ggab90@1130: _nodes.pop_back(); deba@109: } alpar@209: } deba@109: deba@109: public: deba@109: kpeter@735: ///Class to make a snapshot of the digraph and to restore it later. deba@109: kpeter@735: ///Class to make a snapshot of the digraph and to restore it later. deba@109: /// deba@109: ///The newly added nodes and arcs can be removed using the kpeter@735: ///restore() function. This is the only way for deleting nodes and/or kpeter@735: ///arcs from a SmartDigraph structure. deba@109: /// alpar@877: ///\note After a state is restored, you cannot restore a later state, kpeter@735: ///i.e. you cannot add the removed nodes and arcs again using kpeter@735: ///another Snapshot instance. kpeter@735: /// kpeter@735: ///\warning Node splitting cannot be restored. kpeter@735: ///\warning The validity of the snapshot is not stored due to kpeter@735: ///performance reasons. If you do not use the snapshot correctly, kpeter@735: ///it can cause broken program, invalid or not restored state of kpeter@735: ///the digraph or no change. alpar@209: class Snapshot deba@109: { deba@109: SmartDigraph *_graph; deba@109: protected: deba@109: friend class SmartDigraph; deba@109: unsigned int node_num; deba@109: unsigned int arc_num; deba@109: public: deba@109: ///Default constructor. alpar@209: deba@109: ///Default constructor. kpeter@735: ///You have to call save() to actually make a snapshot. deba@109: Snapshot() : _graph(0) {} deba@109: ///Constructor that immediately makes a snapshot alpar@209: kpeter@735: ///This constructor immediately makes a snapshot of the given digraph. kpeter@735: /// kpeter@735: Snapshot(SmartDigraph &gr) : _graph(&gr) { ggab90@1130: node_num=_graph->_nodes.size(); ggab90@1130: arc_num=_graph->_arcs.size(); deba@109: } deba@109: deba@109: ///Make a snapshot. deba@109: kpeter@735: ///This function makes a snapshot of the given digraph. kpeter@735: ///It can be called more than once. In case of a repeated deba@109: ///call, the previous snapshot gets lost. kpeter@735: void save(SmartDigraph &gr) { kpeter@735: _graph=&gr; ggab90@1130: node_num=_graph->_nodes.size(); ggab90@1130: arc_num=_graph->_arcs.size(); deba@109: } deba@109: deba@109: ///Undo the changes until a snapshot. alpar@209: kpeter@735: ///This function undos the changes until the last snapshot kpeter@735: ///created by save() or Snapshot(SmartDigraph&). deba@109: void restore() deba@109: { alpar@209: _graph->restoreSnapshot(*this); deba@109: } deba@109: }; deba@109: }; deba@109: deba@109: deba@109: class SmartGraphBase { deba@109: deba@109: protected: deba@109: deba@109: struct NodeT { deba@109: int first_out; deba@109: }; alpar@209: deba@109: struct ArcT { deba@109: int target; deba@109: int next_out; deba@109: }; deba@109: ggab90@1130: std::vector _nodes; ggab90@1130: std::vector _arcs; deba@109: deba@109: public: alpar@209: kpeter@617: typedef SmartGraphBase Graph; deba@109: deba@109: class Node; deba@109: class Arc; deba@109: class Edge; alpar@209: deba@109: class Node { deba@109: friend class SmartGraphBase; deba@109: protected: deba@109: deba@109: int _id; deba@109: explicit Node(int id) { _id = id;} deba@109: deba@109: public: deba@109: Node() {} deba@109: Node (Invalid) { _id = -1; } deba@109: bool operator==(const Node& node) const {return _id == node._id;} deba@109: bool operator!=(const Node& node) const {return _id != node._id;} deba@109: bool operator<(const Node& node) const {return _id < node._id;} deba@109: }; deba@109: deba@109: class Edge { deba@109: friend class SmartGraphBase; deba@109: protected: deba@109: deba@109: int _id; deba@109: explicit Edge(int id) { _id = id;} deba@109: deba@109: public: deba@109: Edge() {} deba@109: Edge (Invalid) { _id = -1; } deba@109: bool operator==(const Edge& arc) const {return _id == arc._id;} deba@109: bool operator!=(const Edge& arc) const {return _id != arc._id;} deba@109: bool operator<(const Edge& arc) const {return _id < arc._id;} deba@109: }; deba@109: deba@109: class Arc { deba@109: friend class SmartGraphBase; deba@109: protected: deba@109: deba@109: int _id; deba@109: explicit Arc(int id) { _id = id;} deba@109: deba@109: public: kpeter@329: operator Edge() const { kpeter@329: return _id != -1 ? edgeFromId(_id / 2) : INVALID; deba@238: } deba@109: deba@109: Arc() {} deba@109: Arc (Invalid) { _id = -1; } deba@109: bool operator==(const Arc& arc) const {return _id == arc._id;} deba@109: bool operator!=(const Arc& arc) const {return _id != arc._id;} deba@109: bool operator<(const Arc& arc) const {return _id < arc._id;} deba@109: }; deba@109: deba@109: deba@109: deba@109: SmartGraphBase() ggab90@1130: : _nodes(), _arcs() {} deba@109: kpeter@368: typedef True NodeNumTag; kpeter@368: typedef True EdgeNumTag; kpeter@368: typedef True ArcNumTag; kpeter@368: ggab90@1130: int nodeNum() const { return _nodes.size(); } ggab90@1130: int edgeNum() const { return _arcs.size() / 2; } ggab90@1130: int arcNum() const { return _arcs.size(); } alpar@209: ggab90@1130: int maxNodeId() const { return _nodes.size()-1; } ggab90@1130: int maxEdgeId() const { return _arcs.size() / 2 - 1; } ggab90@1130: int maxArcId() const { return _arcs.size()-1; } deba@109: ggab90@1130: Node source(Arc e) const { return Node(_arcs[e._id ^ 1].target); } ggab90@1130: Node target(Arc e) const { return Node(_arcs[e._id].target); } deba@109: ggab90@1130: Node u(Edge e) const { return Node(_arcs[2 * e._id].target); } ggab90@1130: Node v(Edge e) const { return Node(_arcs[2 * e._id + 1].target); } deba@109: deba@109: static bool direction(Arc e) { deba@109: return (e._id & 1) == 1; deba@109: } deba@109: deba@109: static Arc direct(Edge e, bool d) { deba@109: return Arc(e._id * 2 + (d ? 1 : 0)); deba@109: } deba@109: alpar@209: void first(Node& node) const { ggab90@1130: node._id = _nodes.size() - 1; deba@109: } deba@109: kpeter@778: static void next(Node& node) { deba@109: --node._id; deba@109: } deba@109: alpar@209: void first(Arc& arc) const { ggab90@1130: arc._id = _arcs.size() - 1; deba@109: } deba@109: kpeter@778: static void next(Arc& arc) { deba@109: --arc._id; deba@109: } deba@109: alpar@209: void first(Edge& arc) const { ggab90@1130: arc._id = _arcs.size() / 2 - 1; deba@109: } deba@109: kpeter@778: static void next(Edge& arc) { deba@109: --arc._id; deba@109: } deba@109: deba@109: void firstOut(Arc &arc, const Node& v) const { ggab90@1130: arc._id = _nodes[v._id].first_out; deba@109: } deba@109: void nextOut(Arc &arc) const { ggab90@1130: arc._id = _arcs[arc._id].next_out; deba@109: } deba@109: deba@109: void firstIn(Arc &arc, const Node& v) const { ggab90@1130: arc._id = ((_nodes[v._id].first_out) ^ 1); deba@109: if (arc._id == -2) arc._id = -1; deba@109: } deba@109: void nextIn(Arc &arc) const { ggab90@1130: arc._id = ((_arcs[arc._id ^ 1].next_out) ^ 1); deba@109: if (arc._id == -2) arc._id = -1; deba@109: } deba@109: deba@109: void firstInc(Edge &arc, bool& d, const Node& v) const { ggab90@1130: int de = _nodes[v._id].first_out; deba@109: if (de != -1) { deba@109: arc._id = de / 2; deba@109: d = ((de & 1) == 1); deba@109: } else { deba@109: arc._id = -1; deba@109: d = true; deba@109: } deba@109: } deba@109: void nextInc(Edge &arc, bool& d) const { ggab90@1130: int de = (_arcs[(arc._id * 2) | (d ? 1 : 0)].next_out); deba@109: if (de != -1) { deba@109: arc._id = de / 2; deba@109: d = ((de & 1) == 1); deba@109: } else { deba@109: arc._id = -1; alpar@209: d = true; deba@109: } deba@109: } alpar@209: deba@109: static int id(Node v) { return v._id; } deba@109: static int id(Arc e) { return e._id; } deba@109: static int id(Edge e) { return e._id; } deba@109: deba@109: static Node nodeFromId(int id) { return Node(id);} deba@109: static Arc arcFromId(int id) { return Arc(id);} deba@109: static Edge edgeFromId(int id) { return Edge(id);} deba@109: alpar@209: bool valid(Node n) const { ggab90@1130: return n._id >= 0 && n._id < static_cast(_nodes.size()); deba@149: } alpar@209: bool valid(Arc a) const { ggab90@1130: return a._id >= 0 && a._id < static_cast(_arcs.size()); deba@149: } alpar@209: bool valid(Edge e) const { ggab90@1130: return e._id >= 0 && 2 * e._id < static_cast(_arcs.size()); deba@149: } deba@149: alpar@209: Node addNode() { ggab90@1130: int n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); ggab90@1130: _nodes[n].first_out = -1; alpar@209: deba@109: return Node(n); deba@109: } alpar@209: deba@138: Edge addEdge(Node u, Node v) { ggab90@1130: int n = _arcs.size(); ggab90@1130: _arcs.push_back(ArcT()); ggab90@1130: _arcs.push_back(ArcT()); alpar@209: ggab90@1130: _arcs[n].target = u._id; ggab90@1130: _arcs[n | 1].target = v._id; deba@109: ggab90@1130: _arcs[n].next_out = _nodes[v._id].first_out; ggab90@1130: _nodes[v._id].first_out = n; deba@109: ggab90@1130: _arcs[n | 1].next_out = _nodes[u._id].first_out; ggab90@1130: _nodes[u._id].first_out = (n | 1); deba@109: deba@109: return Edge(n / 2); deba@109: } alpar@209: deba@109: void clear() { ggab90@1130: _arcs.clear(); ggab90@1130: _nodes.clear(); deba@109: } deba@109: deba@109: }; deba@109: deba@109: typedef GraphExtender ExtendedSmartGraphBase; deba@109: deba@109: /// \ingroup graphs deba@109: /// deba@109: /// \brief A smart undirected graph class. deba@109: /// kpeter@735: /// \ref SmartGraph is a simple and fast graph implementation. kpeter@735: /// It is also quite memory efficient but at the price alpar@877: /// that it does not support node and edge deletion kpeter@735: /// (except for the Snapshot feature). deba@109: /// kpeter@735: /// This type fully conforms to the \ref concepts::Graph "Graph concept" kpeter@735: /// and it also provides some additional functionalities. kpeter@735: /// Most of its member functions and nested classes are documented kpeter@735: /// only in the concept class. kpeter@735: /// kpeter@787: /// This class provides constant time counting for nodes, edges and arcs. kpeter@787: /// kpeter@735: /// \sa concepts::Graph kpeter@735: /// \sa SmartDigraph deba@109: class SmartGraph : public ExtendedSmartGraphBase { kpeter@617: typedef ExtendedSmartGraphBase Parent; kpeter@617: deba@109: private: kpeter@735: /// Graphs are \e not copy constructible. Use GraphCopy instead. deba@109: SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {}; kpeter@735: /// \brief Assignment of a graph to another one is \e not allowed. kpeter@735: /// Use GraphCopy instead. deba@109: void operator=(const SmartGraph &) {} deba@109: deba@109: public: deba@109: deba@109: /// Constructor alpar@209: deba@109: /// Constructor. deba@109: /// deba@109: SmartGraph() {} deba@109: kpeter@735: /// \brief Add a new node to the graph. kpeter@735: /// kpeter@735: /// This function adds a new node to the graph. kpeter@559: /// \return The new node. deba@109: Node addNode() { return Parent::addNode(); } alpar@209: kpeter@735: /// \brief Add a new edge to the graph. kpeter@735: /// kpeter@735: /// This function adds a new edge to the graph between nodes kpeter@735: /// \c u and \c v with inherent orientation from node \c u to kpeter@735: /// node \c v. kpeter@735: /// \return The new edge. kpeter@735: Edge addEdge(Node u, Node v) { kpeter@735: return Parent::addEdge(u, v); deba@109: } deba@109: deba@149: /// \brief Node validity check deba@149: /// kpeter@735: /// This function gives back \c true if the given node is valid, kpeter@735: /// i.e. it is a real node of the graph. deba@149: /// deba@149: /// \warning A removed node (using Snapshot) could become valid again kpeter@735: /// if new nodes are added to the graph. deba@149: bool valid(Node n) const { return Parent::valid(n); } deba@149: kpeter@735: /// \brief Edge validity check kpeter@735: /// kpeter@735: /// This function gives back \c true if the given edge is valid, kpeter@735: /// i.e. it is a real edge of the graph. kpeter@735: /// kpeter@735: /// \warning A removed edge (using Snapshot) could become valid again kpeter@735: /// if new edges are added to the graph. kpeter@735: bool valid(Edge e) const { return Parent::valid(e); } kpeter@735: deba@149: /// \brief Arc validity check deba@149: /// kpeter@735: /// This function gives back \c true if the given arc is valid, kpeter@735: /// i.e. it is a real arc of the graph. deba@149: /// deba@149: /// \warning A removed arc (using Snapshot) could become valid again kpeter@735: /// if new edges are added to the graph. deba@149: bool valid(Arc a) const { return Parent::valid(a); } deba@149: deba@109: ///Clear the graph. alpar@209: kpeter@735: ///This function erases all nodes and arcs from the graph. deba@109: /// deba@109: void clear() { deba@109: Parent::clear(); deba@109: } deba@109: kpeter@736: /// Reserve memory for nodes. kpeter@736: kpeter@736: /// Using this function, it is possible to avoid superfluous memory kpeter@736: /// allocation: if you know that the graph you want to build will kpeter@736: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@736: /// then it is worth reserving space for this amount before starting kpeter@736: /// to build the graph. kpeter@736: /// \sa reserveEdge() ggab90@1130: void reserveNode(int n) { _nodes.reserve(n); }; kpeter@736: kpeter@736: /// Reserve memory for edges. kpeter@736: kpeter@736: /// Using this function, it is possible to avoid superfluous memory kpeter@736: /// allocation: if you know that the graph you want to build will kpeter@736: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@736: /// then it is worth reserving space for this amount before starting kpeter@736: /// to build the graph. kpeter@736: /// \sa reserveNode() ggab90@1130: void reserveEdge(int m) { _arcs.reserve(2 * m); }; kpeter@736: deba@109: public: alpar@209: deba@109: class Snapshot; deba@109: deba@109: protected: deba@109: deba@109: void saveSnapshot(Snapshot &s) deba@109: { deba@109: s._graph = this; ggab90@1130: s.node_num = _nodes.size(); ggab90@1130: s.arc_num = _arcs.size(); deba@109: } deba@109: deba@109: void restoreSnapshot(const Snapshot &s) deba@109: { ggab90@1130: while(s.arc_num<_arcs.size()) { ggab90@1130: int n=_arcs.size()-1; deba@109: Edge arc=edgeFromId(n/2); alpar@209: Parent::notifier(Edge()).erase(arc); deba@109: std::vector dir; deba@109: dir.push_back(arcFromId(n)); deba@109: dir.push_back(arcFromId(n-1)); alpar@209: Parent::notifier(Arc()).erase(dir); ggab90@1130: _nodes[_arcs[n-1].target].first_out=_arcs[n].next_out; ggab90@1130: _nodes[_arcs[n].target].first_out=_arcs[n-1].next_out; ggab90@1130: _arcs.pop_back(); ggab90@1130: _arcs.pop_back(); deba@109: } ggab90@1130: while(s.node_num<_nodes.size()) { ggab90@1130: int n=_nodes.size()-1; deba@109: Node node = nodeFromId(n); alpar@209: Parent::notifier(Node()).erase(node); ggab90@1130: _nodes.pop_back(); deba@109: } alpar@209: } deba@109: deba@109: public: deba@109: kpeter@735: ///Class to make a snapshot of the graph and to restore it later. deba@109: kpeter@735: ///Class to make a snapshot of the graph and to restore it later. deba@109: /// kpeter@735: ///The newly added nodes and edges can be removed using the kpeter@735: ///restore() function. This is the only way for deleting nodes and/or kpeter@735: ///edges from a SmartGraph structure. deba@109: /// alpar@877: ///\note After a state is restored, you cannot restore a later state, kpeter@735: ///i.e. you cannot add the removed nodes and edges again using kpeter@735: ///another Snapshot instance. deba@109: /// kpeter@735: ///\warning The validity of the snapshot is not stored due to kpeter@735: ///performance reasons. If you do not use the snapshot correctly, kpeter@735: ///it can cause broken program, invalid or not restored state of kpeter@735: ///the graph or no change. alpar@209: class Snapshot deba@109: { deba@109: SmartGraph *_graph; deba@109: protected: deba@109: friend class SmartGraph; deba@109: unsigned int node_num; deba@109: unsigned int arc_num; deba@109: public: deba@109: ///Default constructor. alpar@209: deba@109: ///Default constructor. kpeter@735: ///You have to call save() to actually make a snapshot. deba@109: Snapshot() : _graph(0) {} deba@109: ///Constructor that immediately makes a snapshot alpar@209: kpeter@735: /// This constructor immediately makes a snapshot of the given graph. kpeter@735: /// kpeter@735: Snapshot(SmartGraph &gr) { kpeter@735: gr.saveSnapshot(*this); deba@109: } deba@109: deba@109: ///Make a snapshot. deba@109: kpeter@735: ///This function makes a snapshot of the given graph. kpeter@735: ///It can be called more than once. In case of a repeated deba@109: ///call, the previous snapshot gets lost. kpeter@735: void save(SmartGraph &gr) deba@109: { kpeter@735: gr.saveSnapshot(*this); deba@109: } deba@109: kpeter@735: ///Undo the changes until the last snapshot. alpar@209: kpeter@735: ///This function undos the changes until the last snapshot kpeter@735: ///created by save() or Snapshot(SmartGraph&). deba@109: void restore() deba@109: { deba@109: _graph->restoreSnapshot(*this); deba@109: } deba@109: }; deba@109: }; alpar@209: deba@1019: class SmartBpGraphBase { deba@1019: deba@1019: protected: deba@1019: deba@1019: struct NodeT { deba@1019: int first_out; deba@1019: int partition_next; deba@1019: int partition_index; deba@1019: bool red; deba@1019: }; deba@1019: deba@1019: struct ArcT { deba@1019: int target; deba@1019: int next_out; deba@1019: }; deba@1019: ggab90@1130: std::vector _nodes; ggab90@1130: std::vector _arcs; deba@1019: deba@1019: int first_red, first_blue; deba@1023: int max_red, max_blue; deba@1019: deba@1019: public: deba@1019: deba@1019: typedef SmartBpGraphBase Graph; deba@1019: deba@1019: class Node; deba@1019: class Arc; deba@1019: class Edge; deba@1019: deba@1019: class Node { deba@1019: friend class SmartBpGraphBase; deba@1019: protected: deba@1019: deba@1019: int _id; deba@1019: explicit Node(int id) { _id = id;} deba@1019: deba@1019: public: deba@1019: Node() {} deba@1019: Node (Invalid) { _id = -1; } deba@1019: bool operator==(const Node& node) const {return _id == node._id;} deba@1019: bool operator!=(const Node& node) const {return _id != node._id;} deba@1019: bool operator<(const Node& node) const {return _id < node._id;} deba@1019: }; deba@1019: deba@1025: class RedNode : public Node { deba@1025: friend class SmartBpGraphBase; deba@1025: protected: deba@1025: deba@1025: explicit RedNode(int pid) : Node(pid) {} deba@1025: deba@1025: public: deba@1025: RedNode() {} deba@1025: RedNode(const RedNode& node) : Node(node) {} alpar@1210: RedNode(Invalid) : Node(INVALID) {} alpar@1210: const RedNode& operator=(const RedNode& node) { Node::operator=(node); return *this;} deba@1025: }; deba@1025: deba@1025: class BlueNode : public Node { deba@1025: friend class SmartBpGraphBase; deba@1025: protected: deba@1025: deba@1025: explicit BlueNode(int pid) : Node(pid) {} deba@1025: deba@1025: public: deba@1025: BlueNode() {} deba@1025: BlueNode(const BlueNode& node) : Node(node) {} deba@1025: BlueNode(Invalid) : Node(INVALID){} alpar@1210: const BlueNode& operator=(const BlueNode& node) { Node::operator=(node); return *this;} deba@1025: }; deba@1025: deba@1019: class Edge { deba@1019: friend class SmartBpGraphBase; deba@1019: protected: deba@1019: deba@1019: int _id; deba@1019: explicit Edge(int id) { _id = id;} deba@1019: deba@1019: public: deba@1019: Edge() {} deba@1019: Edge (Invalid) { _id = -1; } deba@1019: bool operator==(const Edge& arc) const {return _id == arc._id;} deba@1019: bool operator!=(const Edge& arc) const {return _id != arc._id;} deba@1019: bool operator<(const Edge& arc) const {return _id < arc._id;} deba@1019: }; deba@1019: deba@1019: class Arc { deba@1019: friend class SmartBpGraphBase; deba@1019: protected: deba@1019: deba@1019: int _id; deba@1019: explicit Arc(int id) { _id = id;} deba@1019: deba@1019: public: deba@1019: operator Edge() const { deba@1019: return _id != -1 ? edgeFromId(_id / 2) : INVALID; deba@1019: } deba@1019: deba@1019: Arc() {} deba@1019: Arc (Invalid) { _id = -1; } deba@1019: bool operator==(const Arc& arc) const {return _id == arc._id;} deba@1019: bool operator!=(const Arc& arc) const {return _id != arc._id;} deba@1019: bool operator<(const Arc& arc) const {return _id < arc._id;} deba@1019: }; deba@1019: deba@1019: deba@1019: deba@1019: SmartBpGraphBase() ggab90@1130: : _nodes(), _arcs(), first_red(-1), first_blue(-1), deba@1023: max_red(-1), max_blue(-1) {} deba@1019: deba@1019: typedef True NodeNumTag; deba@1019: typedef True EdgeNumTag; deba@1019: typedef True ArcNumTag; deba@1019: ggab90@1130: int nodeNum() const { return _nodes.size(); } deba@1023: int redNum() const { return max_red + 1; } deba@1023: int blueNum() const { return max_blue + 1; } ggab90@1130: int edgeNum() const { return _arcs.size() / 2; } ggab90@1130: int arcNum() const { return _arcs.size(); } deba@1019: ggab90@1130: int maxNodeId() const { return _nodes.size()-1; } deba@1023: int maxRedId() const { return max_red; } deba@1023: int maxBlueId() const { return max_blue; } ggab90@1130: int maxEdgeId() const { return _arcs.size() / 2 - 1; } ggab90@1130: int maxArcId() const { return _arcs.size()-1; } deba@1019: ggab90@1130: bool red(Node n) const { return _nodes[n._id].red; } ggab90@1130: bool blue(Node n) const { return !_nodes[n._id].red; } deba@1019: deba@1025: static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); } deba@1025: static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); } deba@1025: ggab90@1130: Node source(Arc a) const { return Node(_arcs[a._id ^ 1].target); } ggab90@1130: Node target(Arc a) const { return Node(_arcs[a._id].target); } deba@1019: deba@1025: RedNode redNode(Edge e) const { ggab90@1130: return RedNode(_arcs[2 * e._id].target); deba@1025: } deba@1025: BlueNode blueNode(Edge e) const { ggab90@1130: return BlueNode(_arcs[2 * e._id + 1].target); deba@1025: } deba@1019: deba@1019: static bool direction(Arc a) { deba@1019: return (a._id & 1) == 1; deba@1019: } deba@1019: deba@1019: static Arc direct(Edge e, bool d) { deba@1019: return Arc(e._id * 2 + (d ? 1 : 0)); deba@1019: } deba@1019: deba@1019: void first(Node& node) const { ggab90@1130: node._id = _nodes.size() - 1; deba@1019: } deba@1019: deba@1019: static void next(Node& node) { deba@1019: --node._id; deba@1019: } deba@1019: deba@1025: void first(RedNode& node) const { deba@1019: node._id = first_red; deba@1019: } deba@1019: deba@1025: void next(RedNode& node) const { ggab90@1130: node._id = _nodes[node._id].partition_next; deba@1019: } deba@1019: deba@1025: void first(BlueNode& node) const { deba@1019: node._id = first_blue; deba@1019: } deba@1019: deba@1025: void next(BlueNode& node) const { ggab90@1130: node._id = _nodes[node._id].partition_next; deba@1019: } deba@1019: deba@1019: void first(Arc& arc) const { ggab90@1130: arc._id = _arcs.size() - 1; deba@1019: } deba@1019: deba@1019: static void next(Arc& arc) { deba@1019: --arc._id; deba@1019: } deba@1019: deba@1019: void first(Edge& arc) const { ggab90@1130: arc._id = _arcs.size() / 2 - 1; deba@1019: } deba@1019: deba@1019: static void next(Edge& arc) { deba@1019: --arc._id; deba@1019: } deba@1019: deba@1019: void firstOut(Arc &arc, const Node& v) const { ggab90@1130: arc._id = _nodes[v._id].first_out; deba@1019: } deba@1019: void nextOut(Arc &arc) const { ggab90@1130: arc._id = _arcs[arc._id].next_out; deba@1019: } deba@1019: deba@1019: void firstIn(Arc &arc, const Node& v) const { ggab90@1130: arc._id = ((_nodes[v._id].first_out) ^ 1); deba@1019: if (arc._id == -2) arc._id = -1; deba@1019: } deba@1019: void nextIn(Arc &arc) const { ggab90@1130: arc._id = ((_arcs[arc._id ^ 1].next_out) ^ 1); deba@1019: if (arc._id == -2) arc._id = -1; deba@1019: } deba@1019: deba@1019: void firstInc(Edge &arc, bool& d, const Node& v) const { ggab90@1130: int de = _nodes[v._id].first_out; deba@1019: if (de != -1) { deba@1019: arc._id = de / 2; deba@1019: d = ((de & 1) == 1); deba@1019: } else { deba@1019: arc._id = -1; deba@1019: d = true; deba@1019: } deba@1019: } deba@1019: void nextInc(Edge &arc, bool& d) const { ggab90@1130: int de = (_arcs[(arc._id * 2) | (d ? 1 : 0)].next_out); deba@1019: if (de != -1) { deba@1019: arc._id = de / 2; deba@1019: d = ((de & 1) == 1); deba@1019: } else { deba@1019: arc._id = -1; deba@1019: d = true; deba@1019: } deba@1019: } deba@1019: deba@1019: static int id(Node v) { return v._id; } ggab90@1130: int id(RedNode v) const { return _nodes[v._id].partition_index; } ggab90@1130: int id(BlueNode v) const { return _nodes[v._id].partition_index; } deba@1019: static int id(Arc e) { return e._id; } deba@1019: static int id(Edge e) { return e._id; } deba@1019: deba@1019: static Node nodeFromId(int id) { return Node(id);} deba@1019: static Arc arcFromId(int id) { return Arc(id);} deba@1019: static Edge edgeFromId(int id) { return Edge(id);} deba@1019: deba@1019: bool valid(Node n) const { ggab90@1130: return n._id >= 0 && n._id < static_cast(_nodes.size()); deba@1019: } deba@1019: bool valid(Arc a) const { ggab90@1130: return a._id >= 0 && a._id < static_cast(_arcs.size()); deba@1019: } deba@1019: bool valid(Edge e) const { ggab90@1130: return e._id >= 0 && 2 * e._id < static_cast(_arcs.size()); deba@1019: } deba@1019: deba@1025: RedNode addRedNode() { ggab90@1130: int n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); ggab90@1130: _nodes[n].first_out = -1; ggab90@1130: _nodes[n].red = true; ggab90@1130: _nodes[n].partition_index = ++max_red; ggab90@1130: _nodes[n].partition_next = first_red; deba@1019: first_red = n; deba@1019: deba@1025: return RedNode(n); deba@1019: } deba@1019: deba@1025: BlueNode addBlueNode() { ggab90@1130: int n = _nodes.size(); ggab90@1130: _nodes.push_back(NodeT()); ggab90@1130: _nodes[n].first_out = -1; ggab90@1130: _nodes[n].red = false; ggab90@1130: _nodes[n].partition_index = ++max_blue; ggab90@1130: _nodes[n].partition_next = first_blue; deba@1019: first_blue = n; deba@1019: deba@1025: return BlueNode(n); deba@1019: } deba@1019: deba@1025: Edge addEdge(RedNode u, BlueNode v) { ggab90@1130: int n = _arcs.size(); ggab90@1130: _arcs.push_back(ArcT()); ggab90@1130: _arcs.push_back(ArcT()); deba@1019: ggab90@1130: _arcs[n].target = u._id; ggab90@1130: _arcs[n | 1].target = v._id; deba@1019: ggab90@1130: _arcs[n].next_out = _nodes[v._id].first_out; ggab90@1130: _nodes[v._id].first_out = n; deba@1019: ggab90@1130: _arcs[n | 1].next_out = _nodes[u._id].first_out; ggab90@1130: _nodes[u._id].first_out = (n | 1); deba@1019: deba@1019: return Edge(n / 2); deba@1019: } deba@1019: deba@1019: void clear() { ggab90@1130: _arcs.clear(); ggab90@1130: _nodes.clear(); deba@1019: first_red = -1; deba@1019: first_blue = -1; deba@1023: max_blue = -1; deba@1023: max_red = -1; deba@1019: } deba@1019: deba@1019: }; deba@1019: deba@1019: typedef BpGraphExtender ExtendedSmartBpGraphBase; deba@1019: deba@1019: /// \ingroup graphs deba@1019: /// deba@1020: /// \brief A smart undirected bipartite graph class. deba@1019: /// deba@1020: /// \ref SmartBpGraph is a simple and fast bipartite graph implementation. deba@1019: /// It is also quite memory efficient but at the price deba@1019: /// that it does not support node and edge deletion deba@1019: /// (except for the Snapshot feature). deba@1019: /// deba@1020: /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept" deba@1019: /// and it also provides some additional functionalities. deba@1019: /// Most of its member functions and nested classes are documented deba@1019: /// only in the concept class. deba@1019: /// deba@1019: /// This class provides constant time counting for nodes, edges and arcs. deba@1019: /// deba@1020: /// \sa concepts::BpGraph deba@1020: /// \sa SmartGraph deba@1019: class SmartBpGraph : public ExtendedSmartBpGraphBase { deba@1019: typedef ExtendedSmartBpGraphBase Parent; deba@1019: deba@1019: private: deba@1019: /// Graphs are \e not copy constructible. Use GraphCopy instead. deba@1019: SmartBpGraph(const SmartBpGraph &) : ExtendedSmartBpGraphBase() {}; deba@1019: /// \brief Assignment of a graph to another one is \e not allowed. deba@1019: /// Use GraphCopy instead. deba@1019: void operator=(const SmartBpGraph &) {} deba@1019: deba@1019: public: deba@1019: deba@1019: /// Constructor deba@1019: deba@1019: /// Constructor. deba@1019: /// deba@1019: SmartBpGraph() {} deba@1019: deba@1019: /// \brief Add a new red node to the graph. deba@1019: /// deba@1019: /// This function adds a red new node to the graph. deba@1019: /// \return The new node. deba@1025: RedNode addRedNode() { return Parent::addRedNode(); } deba@1019: deba@1019: /// \brief Add a new blue node to the graph. deba@1019: /// deba@1019: /// This function adds a blue new node to the graph. deba@1019: /// \return The new node. deba@1025: BlueNode addBlueNode() { return Parent::addBlueNode(); } deba@1019: deba@1019: /// \brief Add a new edge to the graph. deba@1019: /// deba@1019: /// This function adds a new edge to the graph between nodes deba@1019: /// \c u and \c v with inherent orientation from node \c u to deba@1019: /// node \c v. deba@1019: /// \return The new edge. deba@1025: Edge addEdge(RedNode u, BlueNode v) { deba@1025: return Parent::addEdge(u, v); deba@1025: } deba@1025: Edge addEdge(BlueNode v, RedNode u) { deba@1025: return Parent::addEdge(u, v); deba@1019: } deba@1019: deba@1019: /// \brief Node validity check deba@1019: /// deba@1019: /// This function gives back \c true if the given node is valid, deba@1019: /// i.e. it is a real node of the graph. deba@1019: /// deba@1019: /// \warning A removed node (using Snapshot) could become valid again deba@1019: /// if new nodes are added to the graph. deba@1019: bool valid(Node n) const { return Parent::valid(n); } deba@1019: deba@1019: /// \brief Edge validity check deba@1019: /// deba@1019: /// This function gives back \c true if the given edge is valid, deba@1019: /// i.e. it is a real edge of the graph. deba@1019: /// deba@1019: /// \warning A removed edge (using Snapshot) could become valid again deba@1019: /// if new edges are added to the graph. deba@1019: bool valid(Edge e) const { return Parent::valid(e); } deba@1019: deba@1019: /// \brief Arc validity check deba@1019: /// deba@1019: /// This function gives back \c true if the given arc is valid, deba@1019: /// i.e. it is a real arc of the graph. deba@1019: /// deba@1019: /// \warning A removed arc (using Snapshot) could become valid again deba@1019: /// if new edges are added to the graph. deba@1019: bool valid(Arc a) const { return Parent::valid(a); } deba@1019: deba@1019: ///Clear the graph. deba@1019: deba@1019: ///This function erases all nodes and arcs from the graph. deba@1019: /// deba@1019: void clear() { deba@1019: Parent::clear(); deba@1019: } deba@1019: deba@1019: /// Reserve memory for nodes. deba@1019: deba@1019: /// Using this function, it is possible to avoid superfluous memory deba@1019: /// allocation: if you know that the graph you want to build will deba@1019: /// be large (e.g. it will contain millions of nodes and/or edges), deba@1019: /// then it is worth reserving space for this amount before starting deba@1019: /// to build the graph. deba@1019: /// \sa reserveEdge() ggab90@1130: void reserveNode(int n) { _nodes.reserve(n); }; deba@1019: deba@1019: /// Reserve memory for edges. deba@1019: deba@1019: /// Using this function, it is possible to avoid superfluous memory deba@1019: /// allocation: if you know that the graph you want to build will deba@1019: /// be large (e.g. it will contain millions of nodes and/or edges), deba@1019: /// then it is worth reserving space for this amount before starting deba@1019: /// to build the graph. deba@1019: /// \sa reserveNode() ggab90@1130: void reserveEdge(int m) { _arcs.reserve(2 * m); }; deba@1019: deba@1019: public: deba@1019: deba@1019: class Snapshot; deba@1019: deba@1019: protected: deba@1019: deba@1019: void saveSnapshot(Snapshot &s) deba@1019: { deba@1019: s._graph = this; ggab90@1130: s.node_num = _nodes.size(); ggab90@1130: s.arc_num = _arcs.size(); deba@1019: } deba@1019: deba@1019: void restoreSnapshot(const Snapshot &s) deba@1019: { ggab90@1130: while(s.arc_num<_arcs.size()) { ggab90@1130: int n=_arcs.size()-1; deba@1019: Edge arc=edgeFromId(n/2); deba@1019: Parent::notifier(Edge()).erase(arc); deba@1019: std::vector dir; deba@1019: dir.push_back(arcFromId(n)); deba@1019: dir.push_back(arcFromId(n-1)); deba@1019: Parent::notifier(Arc()).erase(dir); ggab90@1130: _nodes[_arcs[n-1].target].first_out=_arcs[n].next_out; ggab90@1130: _nodes[_arcs[n].target].first_out=_arcs[n-1].next_out; ggab90@1130: _arcs.pop_back(); ggab90@1130: _arcs.pop_back(); deba@1019: } ggab90@1130: while(s.node_num<_nodes.size()) { ggab90@1130: int n=_nodes.size()-1; deba@1019: Node node = nodeFromId(n); deba@1019: if (Parent::red(node)) { ggab90@1130: first_red = _nodes[n].partition_next; deba@1023: if (first_red != -1) { ggab90@1130: max_red = _nodes[first_red].partition_index; deba@1023: } else { deba@1023: max_red = -1; deba@1023: } alpar@1092: Parent::notifier(RedNode()).erase(asRedNodeUnsafe(node)); deba@1019: } else { ggab90@1130: first_blue = _nodes[n].partition_next; deba@1023: if (first_blue != -1) { ggab90@1130: max_blue = _nodes[first_blue].partition_index; deba@1023: } else { deba@1023: max_blue = -1; deba@1023: } deba@1025: Parent::notifier(BlueNode()).erase(asBlueNodeUnsafe(node)); deba@1019: } deba@1019: Parent::notifier(Node()).erase(node); ggab90@1130: _nodes.pop_back(); deba@1019: } deba@1019: } deba@1019: deba@1019: public: deba@1019: deba@1019: ///Class to make a snapshot of the graph and to restore it later. deba@1019: deba@1019: ///Class to make a snapshot of the graph and to restore it later. deba@1019: /// deba@1019: ///The newly added nodes and edges can be removed using the deba@1019: ///restore() function. This is the only way for deleting nodes and/or deba@1019: ///edges from a SmartBpGraph structure. deba@1019: /// deba@1019: ///\note After a state is restored, you cannot restore a later state, deba@1019: ///i.e. you cannot add the removed nodes and edges again using deba@1019: ///another Snapshot instance. deba@1019: /// deba@1019: ///\warning The validity of the snapshot is not stored due to deba@1019: ///performance reasons. If you do not use the snapshot correctly, deba@1019: ///it can cause broken program, invalid or not restored state of deba@1019: ///the graph or no change. deba@1019: class Snapshot deba@1019: { deba@1019: SmartBpGraph *_graph; deba@1019: protected: deba@1019: friend class SmartBpGraph; deba@1019: unsigned int node_num; deba@1019: unsigned int arc_num; deba@1019: public: deba@1019: ///Default constructor. deba@1019: deba@1019: ///Default constructor. deba@1019: ///You have to call save() to actually make a snapshot. deba@1019: Snapshot() : _graph(0) {} deba@1019: ///Constructor that immediately makes a snapshot deba@1019: deba@1019: /// This constructor immediately makes a snapshot of the given graph. deba@1019: /// deba@1019: Snapshot(SmartBpGraph &gr) { deba@1019: gr.saveSnapshot(*this); deba@1019: } deba@1019: deba@1019: ///Make a snapshot. deba@1019: deba@1019: ///This function makes a snapshot of the given graph. deba@1019: ///It can be called more than once. In case of a repeated deba@1019: ///call, the previous snapshot gets lost. deba@1019: void save(SmartBpGraph &gr) deba@1019: { deba@1019: gr.saveSnapshot(*this); deba@1019: } deba@1019: deba@1019: ///Undo the changes until the last snapshot. deba@1019: deba@1019: ///This function undos the changes until the last snapshot deba@1019: ///created by save() or Snapshot(SmartBpGraph&). deba@1019: void restore() deba@1019: { deba@1019: _graph->restoreSnapshot(*this); deba@1019: } deba@1019: }; deba@1019: }; deba@1019: deba@109: } //namespace lemon deba@109: deba@109: deba@109: #endif //LEMON_SMART_GRAPH_H