deba@1791: /* -*- C++ -*- deba@1791: * lemon/graph_extender.h - Part of LEMON, a generic C++ optimization library deba@1791: * deba@1791: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi deba@1791: * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, deba@1791: * EGRES). deba@1791: * deba@1791: * Permission to use, modify and distribute this software is granted deba@1791: * provided that this copyright notice appears in all copies. For deba@1791: * precise terms see the accompanying LICENSE file. deba@1791: * deba@1791: * This software is provided "AS IS" with no warranty of any kind, deba@1791: * express or implied, and with no claim as to its suitability for any deba@1791: * purpose. deba@1791: * deba@1791: */ deba@1791: deba@1791: #ifndef LEMON_GRAPH_EXTENDER_H deba@1791: #define LEMON_GRAPH_EXTENDER_H deba@1791: deba@1791: #include deba@1791: deba@1791: namespace lemon { deba@1791: deba@1791: template deba@1791: class GraphExtender : public _Base { deba@1791: public: deba@1791: deba@1791: typedef _Base Parent; deba@1791: typedef GraphExtender Graph; deba@1791: deba@1791: typedef typename Parent::Node Node; deba@1791: typedef typename Parent::Edge Edge; deba@1791: deba@1791: int maxId(Node) const { deba@1791: return Parent::maxNodeId(); deba@1791: } deba@1791: deba@1791: int maxId(Edge) const { deba@1791: return Parent::maxEdgeId(); deba@1791: } deba@1791: deba@1791: Node fromId(int id, Node) const { deba@1791: return Parent::nodeFromId(id); deba@1791: } deba@1791: deba@1791: Edge fromId(int id, Edge) const { deba@1791: return Parent::edgeFromId(id); deba@1791: } deba@1791: deba@1791: Node oppositeNode(const Node &n, const Edge &e) const { deba@1791: if (n == Parent::source(e)) deba@1791: return Parent::target(e); deba@1791: else if(n==Parent::target(e)) deba@1791: return Parent::source(e); deba@1791: else deba@1791: return INVALID; deba@1791: } deba@1791: deba@1791: }; deba@1791: deba@1791: template deba@1791: class UndirGraphExtender : public _Base { deba@1791: typedef _Base Parent; deba@1791: typedef UndirGraphExtender Graph; deba@1791: deba@1791: public: deba@1791: deba@1791: typedef typename Parent::Edge UndirEdge; deba@1791: typedef typename Parent::Node Node; deba@1791: deba@1791: class Edge : public UndirEdge { deba@1791: friend class UndirGraphExtender; deba@1791: deba@1791: protected: deba@1791: // FIXME: Marci use opposite logic in his graph adaptors. It would deba@1791: // be reasonable to syncronize... deba@1791: bool forward; deba@1791: deba@1791: Edge(const UndirEdge &ue, bool _forward) : deba@1791: UndirEdge(ue), forward(_forward) {} deba@1791: deba@1791: public: deba@1791: Edge() {} deba@1791: deba@1791: /// Invalid edge constructor deba@1791: Edge(Invalid i) : UndirEdge(i), forward(true) {} deba@1791: deba@1791: bool operator==(const Edge &that) const { deba@1791: return forward==that.forward && UndirEdge(*this)==UndirEdge(that); deba@1791: } deba@1791: bool operator!=(const Edge &that) const { deba@1791: return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that); deba@1791: } deba@1791: bool operator<(const Edge &that) const { deba@1791: return forward> 1), bool(id & 1)); deba@1791: } deba@1791: deba@1791: UndirEdge undirEdgeFromId(int id) const { deba@1791: return Parent::edgeFromId(id >> 1); deba@1791: } deba@1791: deba@1791: Node fromId(int id, Node) const { deba@1791: return nodeFromId(id); deba@1791: } deba@1791: deba@1791: Edge fromId(int id, Edge) const { deba@1791: return edgeFromId(id); deba@1791: } deba@1791: deba@1791: UndirEdge fromId(int id, UndirEdge) const { deba@1791: return undirEdgeFromId(id); deba@1791: } deba@1791: deba@1791: deba@1791: Edge findEdge(Node source, Node target, Edge prev) const { deba@1791: if (prev == INVALID) { deba@1791: UndirEdge edge = Parent::findEdge(source, target); deba@1791: if (edge != INVALID) return direct(edge, true); deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return direct(edge, false); deba@1791: } else if (direction(prev)) { deba@1791: UndirEdge edge = Parent::findEdge(source, target, prev); deba@1791: if (edge != INVALID) return direct(edge, true); deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return direct(edge, false); deba@1791: } else { deba@1791: UndirEdge edge = Parent::findEdge(target, source, prev); deba@1791: if (edge != INVALID) return direct(edge, false); deba@1791: } deba@1791: return INVALID; deba@1791: } deba@1791: deba@1791: UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const { deba@1791: if (prev == INVALID) { deba@1791: UndirEdge edge = Parent::findEdge(source, target); deba@1791: if (edge != INVALID) return edge; deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return edge; deba@1791: } else if (Parent::source(prev) == source) { deba@1791: UndirEdge edge = Parent::findEdge(source, target, prev); deba@1791: if (edge != INVALID) return edge; deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return edge; deba@1791: } else { deba@1791: UndirEdge edge = Parent::findEdge(target, source, prev); deba@1791: if (edge != INVALID) return edge; deba@1791: } deba@1791: return INVALID; deba@1791: } deba@1791: deba@1791: }; deba@1791: deba@1791: } deba@1791: deba@1791: #endif // LEMON_UNDIR_GRAPH_EXTENDER_H