diff -r 60a96465dc49 -r d4e911acef3d src/lemon/smart_graph.h --- a/src/lemon/smart_graph.h Mon Oct 04 16:03:25 2004 +0000 +++ b/src/lemon/smart_graph.h Mon Oct 04 17:13:21 2004 +0000 @@ -26,8 +26,8 @@ #include + #include -#include #include @@ -298,6 +298,381 @@ }; + + + class SymSmartGraph : public SmartGraph { + typedef SmartGraph Parent; + public: + + typedef SymSmartGraph Graph; + + typedef SmartGraph::Node Node; + typedef SmartGraph::NodeIt NodeIt; + + class SymEdge; + class SymEdgeIt; + + class Edge; + class EdgeIt; + class OutEdgeIt; + class InEdgeIt; + + template + class NodeMap : public Parent::NodeMap { + public: + NodeMap(const SymSmartGraph& g) + : SymSmartGraph::Parent::NodeMap(g) {} + NodeMap(const SymSmartGraph& g, Value v) + : SymSmartGraph::Parent::NodeMap(g, v) {} + template + NodeMap(const NodeMap& copy) + : SymSmartGraph::Parent::NodeMap(copy) { } + }; + + template + class SymEdgeMap : public Parent::EdgeMap { + public: + typedef SymEdge KeyType; + + SymEdgeMap(const SymSmartGraph& g) + : SymSmartGraph::Parent::EdgeMap(g) {} + SymEdgeMap(const SymSmartGraph& g, Value v) + : SymSmartGraph::Parent::EdgeMap(g, v) {} + template + SymEdgeMap(const SymEdgeMap& copy) + : SymSmartGraph::Parent::EdgeMap(copy) { } + + }; + + // Create edge map registry. + CREATE_EDGE_MAP_REGISTRY; + // Create edge maps. + CREATE_EDGE_MAP(ArrayMap); + + class Edge { + friend class SymSmartGraph; + friend class SymSmartGraph::EdgeIt; + friend class SymSmartGraph::OutEdgeIt; + friend class SymSmartGraph::InEdgeIt; + + protected: + int id; + + Edge(int pid) { id = pid; } + + public: + /// An Edge with id \c n. + + Edge() { } + Edge (Invalid) { id = -1; } + + operator SymEdge(){ return SymEdge(id >> 1);} + + bool operator==(const Edge i) const {return id == i.id;} + bool operator!=(const Edge i) const {return id != i.id;} + bool operator<(const Edge i) const {return id < i.id;} + // ///Validity check + // operator bool() { return n!=-1; } + }; + + class SymEdge : public SmartGraph::Edge { + friend class SymSmartGraph; + friend class SymSmartGraph::Edge; + typedef SmartGraph::Edge Parent; + + protected: + SymEdge(int pid) : Parent(pid) {} + public: + + SymEdge() { } + SymEdge(const SmartGraph::Edge& i) : Parent(i) {} + SymEdge (Invalid) : Parent(INVALID) {} + + }; + + class OutEdgeIt { + Parent::OutEdgeIt out; + Parent::InEdgeIt in; + public: + OutEdgeIt() {} + OutEdgeIt(const SymSmartGraph& g, Edge e) { + if ((e.id & 1) == 0) { + out = Parent::OutEdgeIt(g, SymEdge(e)); + in = Parent::InEdgeIt(g, g.tail(e)); + } else { + out = Parent::OutEdgeIt(INVALID); + in = Parent::InEdgeIt(g, SymEdge(e)); + } + } + OutEdgeIt (Invalid i) : out(INVALID), in(INVALID) { } + + OutEdgeIt(const SymSmartGraph& g, const Node v) + : out(g, v), in(g, v) {} + OutEdgeIt &operator++() { + if (out != INVALID) { + ++out; + } else { + ++in; + } + return *this; + } + + operator Edge() const { + if (out == INVALID && in == INVALID) return INVALID; + return out != INVALID ? forward(out) : backward(in); + } + + bool operator==(const Edge i) const {return Edge(*this) == i;} + bool operator!=(const Edge i) const {return Edge(*this) != i;} + bool operator<(const Edge i) const {return Edge(*this) < i;} + }; + + class InEdgeIt { + Parent::OutEdgeIt out; + Parent::InEdgeIt in; + public: + InEdgeIt() {} + InEdgeIt(const SymSmartGraph& g, Edge e) { + if ((e.id & 1) == 0) { + out = Parent::OutEdgeIt(g, SymEdge(e)); + in = Parent::InEdgeIt(g, g.tail(e)); + } else { + out = Parent::OutEdgeIt(INVALID); + in = Parent::InEdgeIt(g, SymEdge(e)); + } + } + InEdgeIt (Invalid i) : out(INVALID), in(INVALID) { } + + InEdgeIt(const SymSmartGraph& g, const Node v) + : out(g, v), in(g, v) {} + + InEdgeIt &operator++() { + if (out != INVALID) { + ++out; + } else { + ++in; + } + return *this; + } + + operator Edge() const { + if (out == INVALID && in == INVALID) return INVALID; + return out != INVALID ? backward(out) : forward(in); + } + + bool operator==(const Edge i) const {return Edge(*this) == i;} + bool operator!=(const Edge i) const {return Edge(*this) != i;} + bool operator<(const Edge i) const {return Edge(*this) < i;} + }; + + class SymEdgeIt : public Parent::EdgeIt { + + public: + SymEdgeIt() {} + + SymEdgeIt(const SymSmartGraph& g) + : SymSmartGraph::Parent::EdgeIt(g) {} + + SymEdgeIt(const SymSmartGraph& g, SymEdge e) + : SymSmartGraph::Parent::EdgeIt(g, e) {} + + SymEdgeIt(Invalid i) + : SymSmartGraph::Parent::EdgeIt(INVALID) {} + + SymEdgeIt& operator++() { + SymSmartGraph::Parent::EdgeIt::operator++(); + return *this; + } + + operator SymEdge() const { + return SymEdge + (static_cast(*this)); + } + bool operator==(const SymEdge i) const {return SymEdge(*this) == i;} + bool operator!=(const SymEdge i) const {return SymEdge(*this) != i;} + bool operator<(const SymEdge i) const {return SymEdge(*this) < i;} + }; + + class EdgeIt { + SymEdgeIt it; + bool fw; + public: + EdgeIt(const SymSmartGraph& g) : it(g), fw(true) {} + EdgeIt (Invalid i) : it(i) { } + EdgeIt(const SymSmartGraph& g, Edge e) + : it(g, SymEdge(e)), fw(id(e) & 1 == 0) { } + EdgeIt() { } + EdgeIt& operator++() { + fw = !fw; + if (fw) ++it; + return *this; + } + operator Edge() const { + if (it == INVALID) return INVALID; + return fw ? forward(it) : backward(it); + } + bool operator==(const Edge i) const {return Edge(*this) == i;} + bool operator!=(const Edge i) const {return Edge(*this) != i;} + bool operator<(const Edge i) const {return Edge(*this) < i;} + + }; + + ///Number of nodes. + int nodeNum() const { return Parent::nodeNum(); } + ///Number of edges. + int edgeNum() const { return 2*Parent::edgeNum(); } + ///Number of symmetric edges. + int symEdgeNum() const { return Parent::edgeNum(); } + + /// Maximum node ID. + + /// Maximum node ID. + ///\sa id(Node) + int maxNodeId() const { return Parent::maxNodeId(); } + /// Maximum edge ID. + + /// Maximum edge ID. + ///\sa id(Edge) + int maxEdgeId() const { return 2*Parent::maxEdgeId(); } + /// Maximum symmetric edge ID. + + /// Maximum symmetric edge ID. + ///\sa id(SymEdge) + int maxSymEdgeId() const { return Parent::maxEdgeId(); } + + + Node tail(Edge e) const { + return (e.id & 1) == 0 ? + Parent::tail(SymEdge(e)) : Parent::head(SymEdge(e)); + } + + Node head(Edge e) const { + return (e.id & 1) == 0 ? + Parent::head(SymEdge(e)) : Parent::tail(SymEdge(e)); + } + + Node tail(SymEdge e) const { + return Parent::tail(e); + } + + Node head(SymEdge e) const { + return Parent::head(e); + } + + NodeIt& first(NodeIt& v) const { + v=NodeIt(*this); return v; } + EdgeIt& first(EdgeIt& e) const { + e=EdgeIt(*this); return e; } + SymEdgeIt& first(SymEdgeIt& e) const { + e=SymEdgeIt(*this); return e; } + OutEdgeIt& first(OutEdgeIt& e, const Node v) const { + e=OutEdgeIt(*this,v); return e; } + InEdgeIt& first(InEdgeIt& e, const Node v) const { + e=InEdgeIt(*this,v); return e; } + + /// 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 Parent::id(v); } + /// 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.id; } + + /// The ID of a valid SymEdge is a nonnegative integer not greater than + /// \ref maxSymEdgeId(). The range of the ID's is not surely continuous + /// and the greatest edge ID can be actually less then \ref maxSymEdgeId(). + /// + /// The ID of the \ref INVALID symmetric edge is -1. + ///\return The ID of the edge \c e. + static int id(SymEdge e) { return Parent::id(e); } + + /// Adds a new node to the graph. + + /// \warning It adds the new node to the front of the list. + /// (i.e. the lastly added node becomes the first.) + Node addNode() { + return Parent::addNode(); + } + + SymEdge addEdge(Node u, Node v) { + SymEdge se = Parent::addEdge(u, v); + edge_maps.add(forward(se)); + edge_maps.add(backward(se)); + return se; + } + + /// 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 INVALID if there is no such an edge. + Edge findEdge(Node u, Node v, Edge prev = INVALID) + { + if (prev == INVALID || id(prev) & 1 == 0) { + SymEdge se = Parent::findEdge(u, v, SymEdge(prev)); + if (se != INVALID) return forward(se); + } else { + SymEdge se = Parent::findEdge(v, u, SymEdge(prev)); + if (se != INVALID) return backward(se); + } + return INVALID; + } + +// /// Finds an symmetric edge between two nodes. + +// /// Finds an symmetric 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 INVALID if there is no such an edge. + +// SymEdge findEdge(Node u, Node v, SymEdge prev = INVALID) +// { +// if (prev == INVALID || id(prev) & 1 == 0) { +// SymEdge se = Parent::findEdge(u, v, SymEdge(prev)); +// if (se != INVALID) return se; +// } else { +// SymEdge se = Parent::findEdge(v, u, SymEdge(prev)); +// if (se != INVALID) return se; +// } +// return INVALID; +// } + + public: + + void clear() { + edge_maps.clear(); + Parent::clear(); + } + + static Edge opposite(Edge e) { + return Edge(id(e) ^ 1); + } + + static Edge forward(SymEdge e) { + return Edge(id(e) << 1); + } + + static Edge backward(SymEdge e) { + return Edge((id(e) << 1) | 1); + } + + }; ///Graph for bidirectional edges. ///The purpose of this graph structure is to handle graphs @@ -318,7 +693,7 @@ ///it is not possible to delete edges or nodes from the graph. //\sa SmartGraph. - class SymSmartGraph : public SmartGraph + /* class SymSmartGraph : public SmartGraph { public: typedef SymSmartGraph Graph; @@ -353,7 +728,7 @@ } - }; + };*/ /// @} } //namespace lemon