/* -*- C++ -*- * lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_SMART_GRAPH_H #define LEMON_SMART_GRAPH_H ///\ingroup graphs ///\file ///\brief SmartGraph and SymSmartGraph classes. #include #include #include #include #include #include #include #include #include namespace lemon { class SmartGraph; ///Base of SmartGraph ///Base of SmartGraph /// class SmartGraphBase { friend class SmatGraph; protected: struct NodeT { int first_in,first_out; NodeT() : first_in(-1), first_out(-1) {} }; struct EdgeT { int target, source, next_in, next_out; //FIXME: is this necessary? EdgeT() : next_in(-1), next_out(-1) {} }; std::vector nodes; std::vector edges; public: typedef SmartGraphBase Graph; class Node; class Edge; public: SmartGraphBase() : nodes(), edges() { } SmartGraphBase(const SmartGraphBase &_g) : nodes(_g.nodes), edges(_g.edges) { } typedef True NodeNumTag; typedef True EdgeNumTag; ///Number of nodes. int nodeNum() const { return nodes.size(); } ///Number of edges. int edgeNum() const { return edges.size(); } /// Maximum node ID. /// Maximum node ID. ///\sa id(Node) int maxId(Node = INVALID) const { return nodes.size()-1; } /// Maximum edge ID. /// Maximum edge ID. ///\sa id(Edge) int maxId(Edge = INVALID) const { return edges.size()-1; } Node source(Edge e) const { return edges[e.n].source; } Node target(Edge e) const { return edges[e.n].target; } /// Node ID. /// The ID of a valid Node is a nonnegative integer not greater than /// \ref maxNodeId(). The range of the ID's is not surely continuous /// and the greatest node ID can be actually less then \ref maxNodeId(). /// /// The ID of the \ref INVALID node is -1. ///\return The ID of the node \c v. static int id(Node v) { return v.n; } /// Edge ID. /// The ID of a valid Edge is a nonnegative integer not greater than /// \ref maxEdgeId(). The range of the ID's is not surely continuous /// and the greatest edge ID can be actually less then \ref maxEdgeId(). /// /// The ID of the \ref INVALID edge is -1. ///\return The ID of the edge \c e. static int id(Edge e) { return e.n; } static Node fromId(int id, Node) { return Node(id);} static Edge fromId(int id, Edge) { return Edge(id);} Node addNode() { Node n; n.n=nodes.size(); nodes.push_back(NodeT()); //FIXME: Hmmm... return n; } Edge addEdge(Node u, Node v) { Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... edges[e.n].source=u.n; edges[e.n].target=v.n; edges[e.n].next_out=nodes[u.n].first_out; edges[e.n].next_in=nodes[v.n].first_in; nodes[u.n].first_out=nodes[v.n].first_in=e.n; return e; } void clear() { edges.clear(); nodes.clear(); } class Node { friend class SmartGraphBase; friend class SmartGraph; protected: int n; ///\todo It should be removed (or at least define a setToId() instead). /// Node(int nn) {n=nn;} public: Node() {} Node (Invalid) { n=-1; } bool operator==(const Node i) const {return n==i.n;} bool operator!=(const Node i) const {return n!=i.n;} bool operator<(const Node i) const {return n AlterableSmartGraphBase; typedef IterableGraphExtender IterableSmartGraphBase; typedef DefaultMappableGraphExtender MappableSmartGraphBase; typedef ExtendableGraphExtender ExtendableSmartGraphBase; typedef ClearableGraphExtender ClearableSmartGraphBase; /// \addtogroup graphs /// @{ ///A smart graph class. ///This is a simple and fast graph implementation. ///It is also quite memory efficient, but at the price ///that it does support only limited (only stack-like) ///node and edge deletions. ///It conforms to ///the \ref concept::ExtendableGraph "ExtendableGraph" concept. ///\sa concept::ExtendableGraph. /// ///\author Alpar Juttner class SmartGraph : public ClearableSmartGraphBase { public: /// Finds an edge between two nodes. /// Finds an edge from node \c u to node \c v. /// /// If \c prev is \ref INVALID (this is the default value), then /// it finds the first edge from \c u to \c v. Otherwise it looks for /// the next edge from \c u to \c v after \c prev. /// \return The found edge or \ref INVALID if there is no such an edge. /// /// Thus you can iterate through each edge from \c u to \c v as it follows. /// \code /// for(Edge e=G.findEdge(u,v);e!=INVALID;e=G.findEdge(u,v,e)) { /// ... /// } /// \endcode /// \todo Possibly it should be a global function. Edge findEdge(Node u,Node v, Edge prev = INVALID) { return _findEdge(u,v,prev); } class SnapShot; friend class SnapShot; protected: void restoreSnapShot(const SnapShot &s) { while(s.edge_numEdges ///referencing a moved edge remain ///valid. However InEdge's and OutEdge's ///may be invalidated. ///\warning This functionality cannot be used together with the SnapShot ///feature. ///\todo It could be implemented in a bit faster way. Node split(Node n, bool connect = true) { return _split(n,connect); } ///Class to make a snapshot of the graph and to restrore to it later. ///Class to make a snapshot of the graph and to restrore to it later. /// ///The newly added nodes and edges can be removed using the ///restore() function. ///\note After you restore a state, you cannot restore ///a later state, in other word you cannot add again the edges deleted ///by restore() using another SnapShot instance. /// class SnapShot { SmartGraph *g; protected: friend class SmartGraph; unsigned int node_num; unsigned int edge_num; public: ///Default constructor. ///Default constructor. ///To actually make a snapshot you must call save(). /// SnapShot() : g(0) {} ///Constructor that immediately makes a snapshot ///This constructor immediately makes a snapshot of the graph. ///\param _g The graph we make a snapshot of. SnapShot(SmartGraph &_g) :g(&_g) { node_num=g->nodes.size(); edge_num=g->edges.size(); } ///Make a snapshot. ///Make a snapshot of the graph. /// ///This function can be called more than once. In case of a repeated ///call, the previous snapshot gets lost. ///\param _g The graph we make the snapshot of. void save(SmartGraph &_g) { g=&_g; node_num=g->nodes.size(); edge_num=g->edges.size(); } ///Undo the changes until a snapshot. ///Undo the changes until a snapshot created by save(). /// ///\param s an internal stucture given back by save() ///\note After you restored a state, you cannot restore ///a later state, in other word you cannot add again the edges deleted ///by restore(). /// ///\todo This function might be called undo(). void restore() { g->restoreSnapShot(*this); } }; }; /**************** Undirected List Graph ****************/ typedef ClearableUndirGraphExtender< ExtendableUndirGraphExtender< MappableUndirGraphExtender< IterableUndirGraphExtender< AlterableUndirGraphExtender< UndirGraphExtender > > > > > UndirSmartGraphBase; ///A smart undirected graph class. ///This is a simple and fast undirected graph implementation. ///It is also quite memory efficient, but at the price ///that it does support only limited (only stack-like) ///node and edge deletions. ///Except from this it conforms to ///the \ref concept::UndirGraph "UndirGraph" concept. ///\sa concept::UndirGraph. /// ///\todo SnapShot hasn't been implemented yet. /// class UndirSmartGraph : public UndirSmartGraphBase { }; /// @} } //namespace lemon #endif //LEMON_SMART_GRAPH_H