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@1270: * 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: deba@109: std::vector nodes; deba@109: std::vector arcs; alpar@209: deba@109: public: deba@109: kpeter@664: typedef SmartDigraphBase Digraph; deba@109: deba@109: class Node; deba@109: class Arc; deba@109: deba@109: public: deba@109: deba@109: SmartDigraphBase() : nodes(), arcs() { } alpar@209: SmartDigraphBase(const SmartDigraphBase &_g) deba@109: : nodes(_g.nodes), arcs(_g.arcs) { } alpar@209: deba@109: typedef True NodeNumTag; kpeter@372: typedef True ArcNumTag; deba@109: deba@109: int nodeNum() const { return nodes.size(); } deba@109: int arcNum() const { return arcs.size(); } deba@109: deba@109: int maxNodeId() const { return nodes.size()-1; } deba@109: int maxArcId() const { return arcs.size()-1; } deba@109: deba@109: Node addNode() { alpar@209: int n = nodes.size(); deba@109: nodes.push_back(NodeT()); deba@109: nodes[n].first_in = -1; deba@109: nodes[n].first_out = -1; deba@109: return Node(n); deba@109: } alpar@209: deba@109: Arc addArc(Node u, Node v) { alpar@209: int n = arcs.size(); deba@109: arcs.push_back(ArcT()); alpar@209: arcs[n].source = u._id; deba@109: arcs[n].target = v._id; deba@109: arcs[n].next_out = nodes[u._id].first_out; deba@109: arcs[n].next_in = nodes[v._id].first_in; deba@109: 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() { deba@109: arcs.clear(); deba@109: nodes.clear(); deba@109: } deba@109: deba@109: Node source(Arc a) const { return Node(arcs[a._id].source); } deba@109: 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 { alpar@209: return n._id >= 0 && n._id < static_cast(nodes.size()); deba@149: } alpar@209: bool valid(Arc a) const { alpar@209: 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 { deba@109: 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 { deba@109: 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 { deba@109: arc._id = nodes[node._id].first_out; deba@109: } deba@109: deba@109: void nextOut(Arc& arc) const { deba@109: arc._id = arcs[arc._id].next_out; deba@109: } deba@109: deba@109: void firstIn(Arc& arc, const Node& node) const { deba@109: arc._id = nodes[node._id].first_in; deba@109: } alpar@209: deba@109: void nextIn(Arc& arc) const { deba@109: 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@782: ///\ref SmartDigraph is a simple and fast digraph implementation. kpeter@782: ///It is also quite memory efficient but at the price alpar@956: ///that it does not support node and arc deletion kpeter@782: ///(except for the Snapshot feature). deba@109: /// kpeter@782: ///This type fully conforms to the \ref concepts::Digraph "Digraph concept" kpeter@782: ///and it also provides some additional functionalities. kpeter@782: ///Most of its member functions and nested classes are documented kpeter@782: ///only in the concept class. kpeter@782: /// kpeter@834: ///This class provides constant time counting for nodes and arcs. kpeter@834: /// kpeter@782: ///\sa concepts::Digraph kpeter@782: ///\sa SmartGraph deba@109: class SmartDigraph : public ExtendedSmartDigraphBase { deba@109: typedef ExtendedSmartDigraphBase Parent; deba@109: deba@109: private: kpeter@782: /// Digraphs are \e not copy constructible. Use DigraphCopy instead. deba@109: SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {}; kpeter@782: /// \brief Assignment of a digraph to another one is \e not allowed. kpeter@782: /// 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@782: ///This function adds a new node to the digraph. kpeter@782: ///\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@782: ///This function adds a new arc to the digraph with source node \c s deba@109: ///and target node \c t. kpeter@606: ///\return The new arc. kpeter@782: Arc addArc(Node s, Node t) { alpar@209: return Parent::addArc(s, t); deba@109: } deba@109: deba@149: /// \brief Node validity check deba@149: /// kpeter@782: /// This function gives back \c true if the given node is valid, kpeter@782: /// i.e. it is a real node of the digraph. deba@149: /// deba@149: /// \warning A removed node (using Snapshot) could become valid again kpeter@782: /// 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@782: /// This function gives back \c true if the given arc is valid, kpeter@782: /// i.e. it is a real arc of the digraph. deba@149: /// deba@149: /// \warning A removed arc (using Snapshot) could become valid again kpeter@782: /// 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@782: ///This function splits the given node. First, a new node is added kpeter@782: ///to the digraph, then the source of each outgoing arc of node \c n kpeter@782: ///is moved to this new node. kpeter@782: ///If the second parameter \c connect is \c true (this is the default kpeter@782: ///value), then a new arc from node \c n to the newly created node kpeter@782: ///is also added. deba@109: ///\return The newly created node. deba@109: /// kpeter@782: ///\note All iterators remain valid. kpeter@782: /// 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(); deba@109: nodes[b._id].first_out=nodes[n._id].first_out; deba@109: nodes[n._id].first_out=-1; kpeter@382: for(int i=nodes[b._id].first_out; i!=-1; i=arcs[i].next_out) { kpeter@382: arcs[i].source=b._id; kpeter@382: } deba@109: if(connect) addArc(n,b); deba@109: return b; deba@109: } deba@109: kpeter@782: ///Clear the digraph. kpeter@782: kpeter@782: ///This function erases all nodes and arcs from the digraph. kpeter@782: /// kpeter@782: void clear() { kpeter@782: Parent::clear(); kpeter@782: } kpeter@782: kpeter@782: /// Reserve memory for nodes. kpeter@782: kpeter@782: /// Using this function, it is possible to avoid superfluous memory kpeter@782: /// allocation: if you know that the digraph you want to build will kpeter@782: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@782: /// then it is worth reserving space for this amount before starting kpeter@782: /// to build the digraph. kpeter@782: /// \sa reserveArc() kpeter@782: void reserveNode(int n) { nodes.reserve(n); }; kpeter@782: kpeter@782: /// Reserve memory for arcs. kpeter@782: kpeter@782: /// Using this function, it is possible to avoid superfluous memory kpeter@782: /// allocation: if you know that the digraph you want to build will kpeter@782: /// be large (e.g. it will contain millions of nodes and/or arcs), kpeter@782: /// then it is worth reserving space for this amount before starting kpeter@782: /// to build the digraph. kpeter@782: /// \sa reserveNode() kpeter@782: void reserveArc(int m) { arcs.reserve(m); }; kpeter@782: deba@109: public: alpar@209: deba@109: class Snapshot; deba@109: deba@109: protected: deba@109: deba@109: void restoreSnapshot(const Snapshot &s) deba@109: { deba@109: while(s.arc_numnodes.size(); alpar@209: arc_num=_graph->arcs.size(); deba@109: } deba@109: deba@109: ///Make a snapshot. deba@109: kpeter@782: ///This function makes a snapshot of the given digraph. kpeter@782: ///It can be called more than once. In case of a repeated deba@109: ///call, the previous snapshot gets lost. kpeter@782: void save(SmartDigraph &gr) { kpeter@782: _graph=&gr; alpar@209: node_num=_graph->nodes.size(); alpar@209: arc_num=_graph->arcs.size(); deba@109: } deba@109: deba@109: ///Undo the changes until a snapshot. alpar@209: kpeter@782: ///This function undos the changes until the last snapshot kpeter@782: ///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: deba@109: std::vector nodes; deba@109: std::vector arcs; deba@109: deba@109: public: alpar@209: kpeter@664: 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@341: operator Edge() const { kpeter@341: 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() deba@109: : nodes(), arcs() {} deba@109: kpeter@380: typedef True NodeNumTag; kpeter@380: typedef True EdgeNumTag; kpeter@380: typedef True ArcNumTag; kpeter@380: kpeter@380: int nodeNum() const { return nodes.size(); } kpeter@380: int edgeNum() const { return arcs.size() / 2; } kpeter@380: int arcNum() const { return arcs.size(); } alpar@209: alpar@209: int maxNodeId() const { return nodes.size()-1; } deba@109: int maxEdgeId() const { return arcs.size() / 2 - 1; } deba@109: int maxArcId() const { return arcs.size()-1; } deba@109: deba@109: Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); } deba@109: Node target(Arc e) const { return Node(arcs[e._id].target); } deba@109: deba@125: Node u(Edge e) const { return Node(arcs[2 * e._id].target); } deba@125: 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 { deba@109: node._id = nodes.size() - 1; deba@109: } deba@109: kpeter@825: static void next(Node& node) { deba@109: --node._id; deba@109: } deba@109: alpar@209: void first(Arc& arc) const { deba@109: arc._id = arcs.size() - 1; deba@109: } deba@109: kpeter@825: static void next(Arc& arc) { deba@109: --arc._id; deba@109: } deba@109: alpar@209: void first(Edge& arc) const { deba@109: arc._id = arcs.size() / 2 - 1; deba@109: } deba@109: kpeter@825: static void next(Edge& arc) { deba@109: --arc._id; deba@109: } deba@109: deba@109: void firstOut(Arc &arc, const Node& v) const { deba@109: arc._id = nodes[v._id].first_out; deba@109: } deba@109: void nextOut(Arc &arc) const { deba@109: arc._id = arcs[arc._id].next_out; deba@109: } deba@109: deba@109: void firstIn(Arc &arc, const Node& v) const { deba@109: 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 { deba@109: 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 { deba@109: 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 { deba@109: 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 { alpar@209: return n._id >= 0 && n._id < static_cast(nodes.size()); deba@149: } alpar@209: bool valid(Arc a) const { deba@149: return a._id >= 0 && a._id < static_cast(arcs.size()); deba@149: } alpar@209: bool valid(Edge e) const { alpar@209: return e._id >= 0 && 2 * e._id < static_cast(arcs.size()); deba@149: } deba@149: alpar@209: Node addNode() { deba@109: int n = nodes.size(); deba@109: nodes.push_back(NodeT()); deba@109: nodes[n].first_out = -1; alpar@209: deba@109: return Node(n); deba@109: } alpar@209: deba@138: Edge addEdge(Node u, Node v) { deba@109: int n = arcs.size(); deba@109: arcs.push_back(ArcT()); deba@109: arcs.push_back(ArcT()); alpar@209: deba@109: arcs[n].target = u._id; deba@109: arcs[n | 1].target = v._id; deba@109: deba@109: arcs[n].next_out = nodes[v._id].first_out; deba@109: nodes[v._id].first_out = n; deba@109: alpar@209: arcs[n | 1].next_out = nodes[u._id].first_out; deba@109: nodes[u._id].first_out = (n | 1); deba@109: deba@109: return Edge(n / 2); deba@109: } alpar@209: deba@109: void clear() { deba@109: arcs.clear(); deba@109: 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@782: /// \ref SmartGraph is a simple and fast graph implementation. kpeter@782: /// It is also quite memory efficient but at the price alpar@956: /// that it does not support node and edge deletion kpeter@782: /// (except for the Snapshot feature). deba@109: /// kpeter@782: /// This type fully conforms to the \ref concepts::Graph "Graph concept" kpeter@782: /// and it also provides some additional functionalities. kpeter@782: /// Most of its member functions and nested classes are documented kpeter@782: /// only in the concept class. kpeter@782: /// kpeter@834: /// This class provides constant time counting for nodes, edges and arcs. kpeter@834: /// kpeter@782: /// \sa concepts::Graph kpeter@782: /// \sa SmartDigraph deba@109: class SmartGraph : public ExtendedSmartGraphBase { kpeter@664: typedef ExtendedSmartGraphBase Parent; kpeter@664: deba@109: private: kpeter@782: /// Graphs are \e not copy constructible. Use GraphCopy instead. deba@109: SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {}; kpeter@782: /// \brief Assignment of a graph to another one is \e not allowed. kpeter@782: /// 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@782: /// \brief Add a new node to the graph. kpeter@782: /// kpeter@782: /// This function adds a new node to the graph. kpeter@606: /// \return The new node. deba@109: Node addNode() { return Parent::addNode(); } alpar@209: kpeter@782: /// \brief Add a new edge to the graph. kpeter@782: /// kpeter@782: /// This function adds a new edge to the graph between nodes kpeter@782: /// \c u and \c v with inherent orientation from node \c u to kpeter@782: /// node \c v. kpeter@782: /// \return The new edge. kpeter@782: Edge addEdge(Node u, Node v) { kpeter@782: return Parent::addEdge(u, v); deba@109: } deba@109: deba@149: /// \brief Node validity check deba@149: /// kpeter@782: /// This function gives back \c true if the given node is valid, kpeter@782: /// i.e. it is a real node of the graph. deba@149: /// deba@149: /// \warning A removed node (using Snapshot) could become valid again kpeter@782: /// if new nodes are added to the graph. deba@149: bool valid(Node n) const { return Parent::valid(n); } deba@149: kpeter@782: /// \brief Edge validity check kpeter@782: /// kpeter@782: /// This function gives back \c true if the given edge is valid, kpeter@782: /// i.e. it is a real edge of the graph. kpeter@782: /// kpeter@782: /// \warning A removed edge (using Snapshot) could become valid again kpeter@782: /// if new edges are added to the graph. kpeter@782: bool valid(Edge e) const { return Parent::valid(e); } kpeter@782: deba@149: /// \brief Arc validity check deba@149: /// kpeter@782: /// This function gives back \c true if the given arc is valid, kpeter@782: /// i.e. it is a real arc of the graph. deba@149: /// deba@149: /// \warning A removed arc (using Snapshot) could become valid again kpeter@782: /// 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@782: ///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@783: /// Reserve memory for nodes. kpeter@783: kpeter@783: /// Using this function, it is possible to avoid superfluous memory kpeter@783: /// allocation: if you know that the graph you want to build will kpeter@783: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@783: /// then it is worth reserving space for this amount before starting kpeter@783: /// to build the graph. kpeter@783: /// \sa reserveEdge() kpeter@783: void reserveNode(int n) { nodes.reserve(n); }; kpeter@783: kpeter@783: /// Reserve memory for edges. kpeter@783: kpeter@783: /// Using this function, it is possible to avoid superfluous memory kpeter@783: /// allocation: if you know that the graph you want to build will kpeter@783: /// be large (e.g. it will contain millions of nodes and/or edges), kpeter@783: /// then it is worth reserving space for this amount before starting kpeter@783: /// to build the graph. kpeter@783: /// \sa reserveNode() kpeter@783: void reserveEdge(int m) { arcs.reserve(2 * m); }; kpeter@783: 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; deba@109: s.node_num = nodes.size(); deba@109: s.arc_num = arcs.size(); deba@109: } deba@109: deba@109: void restoreSnapshot(const Snapshot &s) deba@109: { deba@109: while(s.arc_num dir; deba@109: dir.push_back(arcFromId(n)); deba@109: dir.push_back(arcFromId(n-1)); alpar@209: Parent::notifier(Arc()).erase(dir); kpeter@386: nodes[arcs[n-1].target].first_out=arcs[n].next_out; kpeter@386: nodes[arcs[n].target].first_out=arcs[n-1].next_out; alpar@209: arcs.pop_back(); alpar@209: arcs.pop_back(); deba@109: } deba@109: while(s.node_numrestoreSnapshot(*this); deba@109: } deba@109: }; deba@109: }; alpar@209: deba@1187: class SmartBpGraphBase { deba@1187: deba@1187: protected: deba@1187: deba@1187: struct NodeT { deba@1187: int first_out; deba@1187: int partition_next; deba@1187: int partition_index; deba@1187: bool red; deba@1187: }; deba@1187: deba@1187: struct ArcT { deba@1187: int target; deba@1187: int next_out; deba@1187: }; deba@1187: deba@1187: std::vector nodes; deba@1187: std::vector arcs; deba@1187: deba@1187: int first_red, first_blue; deba@1191: int max_red, max_blue; deba@1187: deba@1187: public: deba@1187: deba@1187: typedef SmartBpGraphBase Graph; deba@1187: deba@1187: class Node; deba@1187: class Arc; deba@1187: class Edge; deba@1187: deba@1187: class Node { deba@1187: friend class SmartBpGraphBase; deba@1187: protected: deba@1187: deba@1187: int _id; deba@1187: explicit Node(int id) { _id = id;} deba@1187: deba@1187: public: deba@1187: Node() {} deba@1187: Node (Invalid) { _id = -1; } deba@1187: bool operator==(const Node& node) const {return _id == node._id;} deba@1187: bool operator!=(const Node& node) const {return _id != node._id;} deba@1187: bool operator<(const Node& node) const {return _id < node._id;} deba@1187: }; deba@1187: deba@1193: class RedNode : public Node { deba@1193: friend class SmartBpGraphBase; deba@1193: protected: deba@1193: deba@1193: explicit RedNode(int pid) : Node(pid) {} deba@1193: deba@1193: public: deba@1193: RedNode() {} deba@1193: RedNode(const RedNode& node) : Node(node) {} deba@1193: RedNode(Invalid) : Node(INVALID){} deba@1193: }; deba@1193: deba@1193: class BlueNode : public Node { deba@1193: friend class SmartBpGraphBase; deba@1193: protected: deba@1193: deba@1193: explicit BlueNode(int pid) : Node(pid) {} deba@1193: deba@1193: public: deba@1193: BlueNode() {} deba@1193: BlueNode(const BlueNode& node) : Node(node) {} deba@1193: BlueNode(Invalid) : Node(INVALID){} deba@1193: }; deba@1193: deba@1187: class Edge { deba@1187: friend class SmartBpGraphBase; deba@1187: protected: deba@1187: deba@1187: int _id; deba@1187: explicit Edge(int id) { _id = id;} deba@1187: deba@1187: public: deba@1187: Edge() {} deba@1187: Edge (Invalid) { _id = -1; } deba@1187: bool operator==(const Edge& arc) const {return _id == arc._id;} deba@1187: bool operator!=(const Edge& arc) const {return _id != arc._id;} deba@1187: bool operator<(const Edge& arc) const {return _id < arc._id;} deba@1187: }; deba@1187: deba@1187: class Arc { deba@1187: friend class SmartBpGraphBase; deba@1187: protected: deba@1187: deba@1187: int _id; deba@1187: explicit Arc(int id) { _id = id;} deba@1187: deba@1187: public: deba@1187: operator Edge() const { deba@1187: return _id != -1 ? edgeFromId(_id / 2) : INVALID; deba@1187: } deba@1187: deba@1187: Arc() {} deba@1187: Arc (Invalid) { _id = -1; } deba@1187: bool operator==(const Arc& arc) const {return _id == arc._id;} deba@1187: bool operator!=(const Arc& arc) const {return _id != arc._id;} deba@1187: bool operator<(const Arc& arc) const {return _id < arc._id;} deba@1187: }; deba@1187: deba@1187: deba@1187: deba@1187: SmartBpGraphBase() deba@1191: : nodes(), arcs(), first_red(-1), first_blue(-1), deba@1191: max_red(-1), max_blue(-1) {} deba@1187: deba@1187: typedef True NodeNumTag; deba@1187: typedef True EdgeNumTag; deba@1187: typedef True ArcNumTag; deba@1187: deba@1187: int nodeNum() const { return nodes.size(); } deba@1191: int redNum() const { return max_red + 1; } deba@1191: int blueNum() const { return max_blue + 1; } deba@1187: int edgeNum() const { return arcs.size() / 2; } deba@1187: int arcNum() const { return arcs.size(); } deba@1187: deba@1187: int maxNodeId() const { return nodes.size()-1; } deba@1191: int maxRedId() const { return max_red; } deba@1191: int maxBlueId() const { return max_blue; } deba@1187: int maxEdgeId() const { return arcs.size() / 2 - 1; } deba@1187: int maxArcId() const { return arcs.size()-1; } deba@1187: deba@1187: bool red(Node n) const { return nodes[n._id].red; } deba@1187: bool blue(Node n) const { return !nodes[n._id].red; } deba@1187: deba@1193: static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); } deba@1193: static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); } deba@1193: deba@1187: Node source(Arc a) const { return Node(arcs[a._id ^ 1].target); } deba@1187: Node target(Arc a) const { return Node(arcs[a._id].target); } deba@1187: deba@1193: RedNode redNode(Edge e) const { deba@1193: return RedNode(arcs[2 * e._id].target); deba@1193: } deba@1193: BlueNode blueNode(Edge e) const { deba@1193: return BlueNode(arcs[2 * e._id + 1].target); deba@1193: } deba@1187: deba@1187: static bool direction(Arc a) { deba@1187: return (a._id & 1) == 1; deba@1187: } deba@1187: deba@1187: static Arc direct(Edge e, bool d) { deba@1187: return Arc(e._id * 2 + (d ? 1 : 0)); deba@1187: } deba@1187: deba@1187: void first(Node& node) const { deba@1187: node._id = nodes.size() - 1; deba@1187: } deba@1187: deba@1187: static void next(Node& node) { deba@1187: --node._id; deba@1187: } deba@1187: deba@1193: void first(RedNode& node) const { deba@1187: node._id = first_red; deba@1187: } deba@1187: deba@1193: void next(RedNode& node) const { deba@1187: node._id = nodes[node._id].partition_next; deba@1187: } deba@1187: deba@1193: void first(BlueNode& node) const { deba@1187: node._id = first_blue; deba@1187: } deba@1187: deba@1193: void next(BlueNode& node) const { deba@1187: node._id = nodes[node._id].partition_next; deba@1187: } deba@1187: deba@1187: void first(Arc& arc) const { deba@1187: arc._id = arcs.size() - 1; deba@1187: } deba@1187: deba@1187: static void next(Arc& arc) { deba@1187: --arc._id; deba@1187: } deba@1187: deba@1187: void first(Edge& arc) const { deba@1187: arc._id = arcs.size() / 2 - 1; deba@1187: } deba@1187: deba@1187: static void next(Edge& arc) { deba@1187: --arc._id; deba@1187: } deba@1187: deba@1187: void firstOut(Arc &arc, const Node& v) const { deba@1187: arc._id = nodes[v._id].first_out; deba@1187: } deba@1187: void nextOut(Arc &arc) const { deba@1187: arc._id = arcs[arc._id].next_out; deba@1187: } deba@1187: deba@1187: void firstIn(Arc &arc, const Node& v) const { deba@1187: arc._id = ((nodes[v._id].first_out) ^ 1); deba@1187: if (arc._id == -2) arc._id = -1; deba@1187: } deba@1187: void nextIn(Arc &arc) const { deba@1187: arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1); deba@1187: if (arc._id == -2) arc._id = -1; deba@1187: } deba@1187: deba@1187: void firstInc(Edge &arc, bool& d, const Node& v) const { deba@1187: int de = nodes[v._id].first_out; deba@1187: if (de != -1) { deba@1187: arc._id = de / 2; deba@1187: d = ((de & 1) == 1); deba@1187: } else { deba@1187: arc._id = -1; deba@1187: d = true; deba@1187: } deba@1187: } deba@1187: void nextInc(Edge &arc, bool& d) const { deba@1187: int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out); deba@1187: if (de != -1) { deba@1187: arc._id = de / 2; deba@1187: d = ((de & 1) == 1); deba@1187: } else { deba@1187: arc._id = -1; deba@1187: d = true; deba@1187: } deba@1187: } deba@1187: deba@1187: static int id(Node v) { return v._id; } deba@1193: int id(RedNode v) const { return nodes[v._id].partition_index; } deba@1193: int id(BlueNode v) const { return nodes[v._id].partition_index; } deba@1187: static int id(Arc e) { return e._id; } deba@1187: static int id(Edge e) { return e._id; } deba@1187: deba@1187: static Node nodeFromId(int id) { return Node(id);} deba@1187: static Arc arcFromId(int id) { return Arc(id);} deba@1187: static Edge edgeFromId(int id) { return Edge(id);} deba@1187: deba@1187: bool valid(Node n) const { deba@1187: return n._id >= 0 && n._id < static_cast(nodes.size()); deba@1187: } deba@1187: bool valid(Arc a) const { deba@1187: return a._id >= 0 && a._id < static_cast(arcs.size()); deba@1187: } deba@1187: bool valid(Edge e) const { deba@1187: return e._id >= 0 && 2 * e._id < static_cast(arcs.size()); deba@1187: } deba@1187: deba@1193: RedNode addRedNode() { deba@1187: int n = nodes.size(); deba@1187: nodes.push_back(NodeT()); deba@1187: nodes[n].first_out = -1; deba@1187: nodes[n].red = true; deba@1191: nodes[n].partition_index = ++max_red; deba@1187: nodes[n].partition_next = first_red; deba@1187: first_red = n; deba@1187: deba@1193: return RedNode(n); deba@1187: } deba@1187: deba@1193: BlueNode addBlueNode() { deba@1187: int n = nodes.size(); deba@1187: nodes.push_back(NodeT()); deba@1187: nodes[n].first_out = -1; deba@1187: nodes[n].red = false; deba@1191: nodes[n].partition_index = ++max_blue; deba@1187: nodes[n].partition_next = first_blue; deba@1187: first_blue = n; deba@1187: deba@1193: return BlueNode(n); deba@1187: } deba@1187: deba@1193: Edge addEdge(RedNode u, BlueNode v) { deba@1187: int n = arcs.size(); deba@1187: arcs.push_back(ArcT()); deba@1187: arcs.push_back(ArcT()); deba@1187: deba@1187: arcs[n].target = u._id; deba@1187: arcs[n | 1].target = v._id; deba@1187: deba@1187: arcs[n].next_out = nodes[v._id].first_out; deba@1187: nodes[v._id].first_out = n; deba@1187: deba@1187: arcs[n | 1].next_out = nodes[u._id].first_out; deba@1187: nodes[u._id].first_out = (n | 1); deba@1187: deba@1187: return Edge(n / 2); deba@1187: } deba@1187: deba@1187: void clear() { deba@1187: arcs.clear(); deba@1187: nodes.clear(); deba@1187: first_red = -1; deba@1187: first_blue = -1; deba@1191: max_blue = -1; deba@1191: max_red = -1; deba@1187: } deba@1187: deba@1187: }; deba@1187: deba@1187: typedef BpGraphExtender ExtendedSmartBpGraphBase; deba@1187: deba@1187: /// \ingroup graphs deba@1187: /// deba@1188: /// \brief A smart undirected bipartite graph class. deba@1187: /// deba@1188: /// \ref SmartBpGraph is a simple and fast bipartite graph implementation. deba@1187: /// It is also quite memory efficient but at the price deba@1187: /// that it does not support node and edge deletion deba@1187: /// (except for the Snapshot feature). deba@1187: /// deba@1188: /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept" deba@1187: /// and it also provides some additional functionalities. deba@1187: /// Most of its member functions and nested classes are documented deba@1187: /// only in the concept class. deba@1187: /// deba@1187: /// This class provides constant time counting for nodes, edges and arcs. deba@1187: /// deba@1188: /// \sa concepts::BpGraph deba@1188: /// \sa SmartGraph deba@1187: class SmartBpGraph : public ExtendedSmartBpGraphBase { deba@1187: typedef ExtendedSmartBpGraphBase Parent; deba@1187: deba@1187: private: deba@1187: /// Graphs are \e not copy constructible. Use GraphCopy instead. deba@1187: SmartBpGraph(const SmartBpGraph &) : ExtendedSmartBpGraphBase() {}; deba@1187: /// \brief Assignment of a graph to another one is \e not allowed. deba@1187: /// Use GraphCopy instead. deba@1187: void operator=(const SmartBpGraph &) {} deba@1187: deba@1187: public: deba@1187: deba@1187: /// Constructor deba@1187: deba@1187: /// Constructor. deba@1187: /// deba@1187: SmartBpGraph() {} deba@1187: deba@1187: /// \brief Add a new red node to the graph. deba@1187: /// deba@1187: /// This function adds a red new node to the graph. deba@1187: /// \return The new node. deba@1193: RedNode addRedNode() { return Parent::addRedNode(); } deba@1187: deba@1187: /// \brief Add a new blue node to the graph. deba@1187: /// deba@1187: /// This function adds a blue new node to the graph. deba@1187: /// \return The new node. deba@1193: BlueNode addBlueNode() { return Parent::addBlueNode(); } deba@1187: deba@1187: /// \brief Add a new edge to the graph. deba@1187: /// deba@1187: /// This function adds a new edge to the graph between nodes deba@1187: /// \c u and \c v with inherent orientation from node \c u to deba@1187: /// node \c v. deba@1187: /// \return The new edge. deba@1193: Edge addEdge(RedNode u, BlueNode v) { deba@1193: return Parent::addEdge(u, v); deba@1193: } deba@1193: Edge addEdge(BlueNode v, RedNode u) { deba@1193: return Parent::addEdge(u, v); deba@1187: } deba@1187: deba@1187: /// \brief Node validity check deba@1187: /// deba@1187: /// This function gives back \c true if the given node is valid, deba@1187: /// i.e. it is a real node of the graph. deba@1187: /// deba@1187: /// \warning A removed node (using Snapshot) could become valid again deba@1187: /// if new nodes are added to the graph. deba@1187: bool valid(Node n) const { return Parent::valid(n); } deba@1187: deba@1187: /// \brief Edge validity check deba@1187: /// deba@1187: /// This function gives back \c true if the given edge is valid, deba@1187: /// i.e. it is a real edge of the graph. deba@1187: /// deba@1187: /// \warning A removed edge (using Snapshot) could become valid again deba@1187: /// if new edges are added to the graph. deba@1187: bool valid(Edge e) const { return Parent::valid(e); } deba@1187: deba@1187: /// \brief Arc validity check deba@1187: /// deba@1187: /// This function gives back \c true if the given arc is valid, deba@1187: /// i.e. it is a real arc of the graph. deba@1187: /// deba@1187: /// \warning A removed arc (using Snapshot) could become valid again deba@1187: /// if new edges are added to the graph. deba@1187: bool valid(Arc a) const { return Parent::valid(a); } deba@1187: deba@1187: ///Clear the graph. deba@1187: deba@1187: ///This function erases all nodes and arcs from the graph. deba@1187: /// deba@1187: void clear() { deba@1187: Parent::clear(); deba@1187: } deba@1187: deba@1187: /// Reserve memory for nodes. deba@1187: deba@1187: /// Using this function, it is possible to avoid superfluous memory deba@1187: /// allocation: if you know that the graph you want to build will deba@1187: /// be large (e.g. it will contain millions of nodes and/or edges), deba@1187: /// then it is worth reserving space for this amount before starting deba@1187: /// to build the graph. deba@1187: /// \sa reserveEdge() deba@1187: void reserveNode(int n) { nodes.reserve(n); }; deba@1187: deba@1187: /// Reserve memory for edges. deba@1187: deba@1187: /// Using this function, it is possible to avoid superfluous memory deba@1187: /// allocation: if you know that the graph you want to build will deba@1187: /// be large (e.g. it will contain millions of nodes and/or edges), deba@1187: /// then it is worth reserving space for this amount before starting deba@1187: /// to build the graph. deba@1187: /// \sa reserveNode() deba@1187: void reserveEdge(int m) { arcs.reserve(2 * m); }; deba@1187: deba@1187: public: deba@1187: deba@1187: class Snapshot; deba@1187: deba@1187: protected: deba@1187: deba@1187: void saveSnapshot(Snapshot &s) deba@1187: { deba@1187: s._graph = this; deba@1187: s.node_num = nodes.size(); deba@1187: s.arc_num = arcs.size(); deba@1187: } deba@1187: deba@1187: void restoreSnapshot(const Snapshot &s) deba@1187: { deba@1187: while(s.arc_num dir; deba@1187: dir.push_back(arcFromId(n)); deba@1187: dir.push_back(arcFromId(n-1)); deba@1187: Parent::notifier(Arc()).erase(dir); deba@1187: nodes[arcs[n-1].target].first_out=arcs[n].next_out; deba@1187: nodes[arcs[n].target].first_out=arcs[n-1].next_out; deba@1187: arcs.pop_back(); deba@1187: arcs.pop_back(); deba@1187: } deba@1187: while(s.node_numrestoreSnapshot(*this); deba@1187: } deba@1187: }; deba@1187: }; deba@1187: deba@109: } //namespace lemon deba@109: deba@109: deba@109: #endif //LEMON_SMART_GRAPH_H