alpar@906: /* -*- C++ -*- alpar@921: * src/lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@906: * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@906: * (Egervary Combinatorial Optimization Research Group, EGRES). alpar@906: * alpar@906: * Permission to use, modify and distribute this software is granted alpar@906: * provided that this copyright notice appears in all copies. For alpar@906: * precise terms see the accompanying LICENSE file. alpar@906: * alpar@906: * This software is provided "AS IS" with no warranty of any kind, alpar@906: * express or implied, and with no claim as to its suitability for any alpar@906: * purpose. alpar@906: * alpar@906: */ alpar@105: alpar@921: #ifndef LEMON_SMART_GRAPH_H alpar@921: #define LEMON_SMART_GRAPH_H alpar@104: klao@491: ///\ingroup graphs alpar@242: ///\file alpar@242: ///\brief SmartGraph and SymSmartGraph classes. alpar@242: alpar@104: #include alpar@104: alpar@921: #include alpar@157: klao@946: #include klao@946: #include klao@946: #include deba@937: klao@946: #include alpar@919: klao@946: #include deba@782: klao@946: #include klao@946: #include klao@946: klao@946: klao@946: #include klao@946: deba@782: alpar@921: namespace lemon { alpar@104: klao@946: /// \addtogroup graphs klao@946: /// @{ alpar@185: alpar@969: ///Base of SmartGraph alpar@969: alpar@969: ///Base of SmartGraph alpar@969: /// klao@946: class SmartGraphBase { alpar@104: alpar@104: struct NodeT alpar@104: { alpar@104: int first_in,first_out; alpar@157: NodeT() : first_in(-1), first_out(-1) {} alpar@104: }; alpar@104: struct EdgeT alpar@104: { alpar@104: int head, tail, next_in, next_out; alpar@104: //FIXME: is this necessary? alpar@157: EdgeT() : next_in(-1), next_out(-1) {} alpar@104: }; alpar@104: alpar@104: std::vector nodes; alpar@129: alpar@104: std::vector edges; alpar@104: alpar@185: alpar@104: public: deba@782: klao@946: typedef SmartGraphBase Graph; alpar@104: alpar@164: class Node; alpar@164: class Edge; alpar@108: alpar@104: alpar@104: public: alpar@104: klao@946: SmartGraphBase() : nodes(), edges() { } klao@946: SmartGraphBase(const SmartGraphBase &_g) : nodes(_g.nodes), edges(_g.edges) { } alpar@104: alpar@813: ///Number of nodes. alpar@813: int nodeNum() const { return nodes.size(); } alpar@813: ///Number of edges. alpar@813: int edgeNum() const { return edges.size(); } alpar@104: alpar@813: /// Maximum node ID. alpar@813: alpar@813: /// Maximum node ID. alpar@813: ///\sa id(Node) alpar@813: int maxNodeId() const { return nodes.size()-1; } alpar@813: /// Maximum edge ID. alpar@813: alpar@813: /// Maximum edge ID. alpar@813: ///\sa id(Edge) alpar@813: int maxEdgeId() const { return edges.size()-1; } alpar@108: alpar@164: Node tail(Edge e) const { return edges[e.n].tail; } alpar@164: Node head(Edge e) const { return edges[e.n].head; } alpar@104: alpar@813: /// Node ID. alpar@813: alpar@813: /// The ID of a valid Node is a nonnegative integer not greater than alpar@813: /// \ref maxNodeId(). The range of the ID's is not surely continuous alpar@813: /// and the greatest node ID can be actually less then \ref maxNodeId(). alpar@813: /// alpar@813: /// The ID of the \ref INVALID node is -1. alpar@813: ///\return The ID of the node \c v. alpar@713: static int id(Node v) { return v.n; } alpar@813: /// Edge ID. alpar@813: alpar@813: /// The ID of a valid Edge is a nonnegative integer not greater than alpar@813: /// \ref maxEdgeId(). The range of the ID's is not surely continuous alpar@813: /// and the greatest edge ID can be actually less then \ref maxEdgeId(). alpar@813: /// alpar@813: /// The ID of the \ref INVALID edge is -1. alpar@813: ///\return The ID of the edge \c e. alpar@713: static int id(Edge e) { return e.n; } alpar@104: alpar@164: Node addNode() { alpar@164: Node n; n.n=nodes.size(); alpar@104: nodes.push_back(NodeT()); //FIXME: Hmmm... alpar@104: return n; alpar@104: } alpar@108: alpar@164: Edge addEdge(Node u, Node v) { alpar@164: Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... alpar@104: edges[e.n].tail=u.n; edges[e.n].head=v.n; alpar@104: edges[e.n].next_out=nodes[u.n].first_out; alpar@104: edges[e.n].next_in=nodes[v.n].first_in; alpar@104: nodes[u.n].first_out=nodes[v.n].first_in=e.n; alpar@108: alpar@104: return e; alpar@104: } alpar@104: deba@782: void clear() { deba@782: edges.clear(); deba@782: nodes.clear(); deba@782: } alpar@104: klao@946: alpar@164: class Node { klao@946: friend class SmartGraphBase; alpar@104: alpar@104: protected: alpar@104: int n; alpar@164: Node(int nn) {n=nn;} alpar@104: public: alpar@164: Node() {} alpar@503: Node (Invalid) { n=-1; } alpar@164: bool operator==(const Node i) const {return n==i.n;} alpar@164: bool operator!=(const Node i) const {return n!=i.n;} alpar@164: bool operator<(const Node i) const {return n AlterableSmartGraphBase; klao@946: typedef IterableGraphExtender IterableSmartGraphBase; klao@946: typedef IdMappableGraphExtender IdMappableSmartGraphBase; klao@946: typedef DefaultMappableGraphExtender MappableSmartGraphBase; klao@946: typedef ExtendableGraphExtender ExtendableSmartGraphBase; klao@946: typedef ClearableGraphExtender ClearableSmartGraphBase; deba@937: alpar@950: ///A smart graph class. deba@937: alpar@950: ///This is a simple and fast graph implementation. alpar@950: ///It is also quite memory efficient, but at the price alpar@950: ///that it does not support node and edge deletion. alpar@950: ///It conforms to klao@959: ///the \ref concept::ExtendableGraph "ExtendableGraph" concept. klao@959: ///\sa concept::ExtendableGraph. alpar@950: /// alpar@950: ///\todo Some member functions could be \c static. alpar@950: /// alpar@950: ///\todo A possibly useful functionality: a function saveState() alpar@950: ///(or snapshot() ) would alpar@950: ///give back a data sturcture X and then the function restoreState(X) alpar@950: ///(or rollBack() ) alpar@950: ///would remove the nodes and edges added after the call of saveState(). alpar@950: ///Of course it should be used as a stack. (Maybe X is not necessary.) alpar@950: /// alpar@950: ///\author Alpar Juttner alpar@969: class SmartGraph :public ClearableSmartGraphBase { alpar@969: public: alpar@969: /// Finds an edge between two nodes. alpar@969: alpar@969: /// Finds an edge from node \c u to node \c v. alpar@969: /// alpar@969: /// If \c prev is \ref INVALID (this is the default value), then alpar@969: /// it finds the first edge from \c u to \c v. Otherwise it looks for alpar@969: /// the next edge from \c u to \c v after \c prev. alpar@969: /// \return The found edge or \ref INVALID if there is no such an edge. alpar@969: /// alpar@969: /// Thus you can iterate through each edge from \c u to \c v as it follows. alpar@969: /// \code alpar@969: /// for(Edge e=G.findEdge(u,v);e!=INVALID;e=G.findEdge(u,v,e)) { alpar@969: /// ... alpar@969: /// } alpar@969: /// \endcode alpar@969: /// \todo Possibly it should be a global function. alpar@969: Edge findEdge(Node u,Node v, Edge prev = INVALID) alpar@969: { alpar@969: return _findEdge(u,v,prev); alpar@969: } alpar@969: }; alpar@950: klao@946: template <> klao@946: int countNodes(const SmartGraph& graph) { klao@946: return graph.nodeNum(); klao@946: } deba@937: klao@946: template <> klao@946: int countEdges(const SmartGraph& graph) { klao@946: return graph.edgeNum(); klao@946: } deba@937: alpar@407: /// @} alpar@921: } //namespace lemon alpar@104: alpar@157: alpar@157: alpar@157: alpar@921: #endif //LEMON_SMART_GRAPH_H