alpar@906: /* -*- C++ -*- alpar@921: * src/lemon/full_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@591: alpar@921: #ifndef LEMON_FULL_GRAPH_H alpar@921: #define LEMON_FULL_GRAPH_H alpar@591: klao@946: klao@946: #include klao@946: klao@946: #include klao@946: klao@946: #include klao@946: #include klao@946: alpar@591: ///\ingroup graphs alpar@591: ///\file alpar@591: ///\brief FullGraph and SymFullGraph classes. alpar@591: alpar@591: alpar@921: #include alpar@591: alpar@921: namespace lemon { alpar@591: alpar@591: /// \addtogroup graphs alpar@591: /// @{ alpar@591: klao@946: class FullGraphBase { alpar@591: int NodeNum; alpar@591: int EdgeNum; alpar@591: public: deba@782: klao@946: typedef FullGraphBase Graph; alpar@591: alpar@591: class Node; alpar@591: class Edge; deba@782: alpar@591: public: alpar@591: klao@946: FullGraphBase() {} klao@946: klao@946: alpar@591: ///Creates a full graph with \c n nodes. klao@946: void construct(int n) { NodeNum = n; EdgeNum = n * n; } alpar@591: /// klao@946: // FullGraphBase(const FullGraphBase &_g) klao@946: // : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { } alpar@591: alpar@813: ///Number of nodes. alpar@813: int nodeNum() const { return NodeNum; } alpar@813: ///Number of edges. alpar@813: int edgeNum() const { return EdgeNum; } alpar@591: alpar@813: /// Maximum node ID. alpar@813: alpar@813: /// Maximum node ID. alpar@813: ///\sa id(Node) alpar@813: int maxNodeId() const { return NodeNum-1; } alpar@813: /// Maximum edge ID. alpar@813: alpar@813: /// Maximum edge ID. alpar@813: ///\sa id(Edge) alpar@813: int maxEdgeId() const { return EdgeNum-1; } alpar@591: klao@946: Node tail(Edge e) const { return e.id % NodeNum; } klao@946: Node head(Edge e) const { return e.id / NodeNum; } alpar@591: alpar@591: 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. klao@946: klao@946: static int id(Node v) { return v.id; } 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. klao@946: static int id(Edge e) { return e.id; } alpar@591: alpar@774: /// Finds an edge between two nodes. alpar@774: alpar@774: /// Finds an edge from node \c u to node \c v. alpar@774: /// alpar@774: /// If \c prev is \ref INVALID (this is the default value), then alpar@774: /// It finds the first edge from \c u to \c v. Otherwise it looks for alpar@774: /// the next edge from \c u to \c v after \c prev. alpar@774: /// \return The found edge or INVALID if there is no such an edge. alpar@774: Edge findEdge(Node u,Node v, Edge prev = INVALID) alpar@774: { klao@946: return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID; alpar@774: } alpar@774: alpar@774: alpar@591: class Node { klao@946: friend class FullGraphBase; alpar@591: alpar@591: protected: klao@946: int id; klao@946: Node(int _id) { id = _id;} alpar@591: public: alpar@591: Node() {} klao@946: Node (Invalid) { id = -1; } klao@946: bool operator==(const Node node) const {return id == node.id;} klao@946: bool operator!=(const Node node) const {return id != node.id;} klao@946: bool operator<(const Node node) const {return id < node.id;} alpar@591: }; alpar@591: klao@946: klao@946: klao@946: class Edge { klao@946: friend class FullGraphBase; klao@946: klao@946: protected: klao@946: int id; // NodeNum * head + tail; klao@946: klao@946: Edge(int _id) : id(_id) {} klao@946: klao@946: Edge(const FullGraphBase& _graph, int tail, int head) klao@946: : id(_graph.NodeNum * head+tail) {} alpar@591: public: klao@946: Edge() { } klao@946: Edge (Invalid) { id = -1; } klao@946: bool operator==(const Edge edge) const {return id == edge.id;} klao@946: bool operator!=(const Edge edge) const {return id != edge.id;} klao@946: bool operator<(const Edge edge) const {return id < edge.id;} alpar@591: }; alpar@591: klao@946: void first(Node& node) const { klao@946: node.id = NodeNum-1; klao@946: } alpar@591: klao@946: static void next(Node& node) { klao@946: --node.id; klao@946: } klao@946: klao@946: void first(Edge& edge) const { klao@946: edge.id = EdgeNum-1; klao@946: } klao@946: klao@946: static void next(Edge& edge) { klao@946: --edge.id; klao@946: } klao@946: klao@946: void firstOut(Edge& edge, const Node& node) const { klao@946: edge.id = EdgeNum + node.id - NodeNum; klao@946: } klao@946: klao@946: void nextOut(Edge& edge) const { klao@946: edge.id -= NodeNum; klao@946: if (edge.id < 0) edge.id = -1; klao@946: } klao@946: klao@946: void firstIn(Edge& edge, const Node& node) const { klao@946: edge.id = node.id * NodeNum; klao@946: } alpar@591: klao@946: void nextIn(Edge& edge) const { klao@946: ++edge.id; klao@946: if (edge.id % NodeNum == 0) edge.id = -1; klao@946: } alpar@591: alpar@591: }; alpar@591: klao@946: klao@946: typedef AlterableGraphExtender AlterableFullGraphBase; klao@946: typedef IterableGraphExtender IterableFullGraphBase; klao@946: typedef IdMappableGraphExtender IdMappableFullGraphBase; klao@946: typedef DefaultMappableGraphExtender MappableFullGraphBase; klao@946: alpar@951: ///A full graph class. alpar@951: alpar@951: ///This is a simple and fast directed full graph implementation. alpar@951: ///It is completely static, so you can neither add nor delete either alpar@951: ///edges or nodes. alpar@951: ///Thus it conforms to klao@959: ///the \ref concept::StaticGraph "StaticGraph" concept klao@959: ///\sa concept::StaticGraph. alpar@951: ///\todo What about loops? alpar@951: ///\todo Don't we need SymEdgeMap? alpar@951: /// alpar@951: ///\author Alpar Juttner klao@946: class FullGraph : public MappableFullGraphBase { klao@946: public: klao@946: klao@946: FullGraph(int n) { construct(n); } klao@946: }; klao@946: klao@946: template <> klao@946: int countNodes(const FullGraph& graph) { klao@946: return graph.nodeNum(); klao@946: } klao@946: klao@946: template <> klao@946: int countEdges(const FullGraph& graph) { klao@946: return graph.edgeNum(); klao@946: } klao@946: alpar@591: /// @} alpar@591: alpar@921: } //namespace lemon alpar@591: alpar@591: alpar@591: alpar@591: alpar@921: #endif //LEMON_FULL_GRAPH_H