marci@174: // -*- c++ -*- marci@259: #ifndef HUGO_GRAPH_WRAPPER_H marci@259: #define HUGO_GRAPH_WRAPPER_H marci@76: marci@174: #include marci@368: #include marci@174: alpar@105: namespace hugo { marci@76: marci@335: /// Graph wrappers marci@335: alpar@344: /// A main parts of HUGOlib are the different graph structures, marci@335: /// generic graph algorithms, graph concepts which couple these, and marci@335: /// graph wrappers. While the previous ones are more or less clear, the marci@335: /// latter notion needs further explanation. marci@335: /// Graph wrappers are graph classes which serve for considering graph alpar@344: /// structures in different ways. A short example makes the notion much alpar@344: /// clearer. alpar@344: /// Suppose that we have an instance \c g of a directed graph alpar@344: /// type say \c ListGraph and an algorithm marci@335: /// \code template int algorithm(const Graph&); \endcode alpar@344: /// is needed to run on the reversely oriented graph. alpar@344: /// It may be expensive (in time or in memory usage) to copy alpar@344: /// \c g with the reverse orientation. marci@335: /// Thus, a wrapper class marci@335: /// \code template class RevGraphWrapper; \endcode is used. marci@335: /// The code looks as follows marci@335: /// \code marci@335: /// ListGraph g; marci@335: /// RevGraphWrapper rgw(g); marci@335: /// int result=algorithm(rgw); marci@335: /// \endcode alpar@344: /// After running the algorithm, the original graph \c g alpar@344: /// remains untouched. Thus the graph wrapper used above is to consider the alpar@344: /// original graph with reverse orientation. marci@335: /// This techniques gives rise to an elegant code, and marci@335: /// based on stable graph wrappers, complex algorithms can be marci@335: /// implemented easily. marci@335: /// In flow, circulation and bipartite matching problems, the residual alpar@344: /// graph is of particular importance. Combining a wrapper implementing alpar@344: /// this, shortest path algorithms and minimum mean cycle algorithms, marci@335: /// a range of weighted and cardinality optimization algorithms can be marci@335: /// obtained. For lack of space, for other examples, alpar@344: /// the interested user is referred to the detailed documentation of graph marci@335: /// wrappers. alpar@344: /// The behavior of graph wrappers can be very different. Some of them keep marci@335: /// capabilities of the original graph while in other cases this would be alpar@344: /// meaningless. This means that the concepts that they are a model of depend marci@335: /// on the graph wrapper, and the wrapped graph(s). alpar@344: /// If an edge of \c rgw is deleted, this is carried out by alpar@344: /// deleting the corresponding edge of \c g. But for a residual marci@335: /// graph, this operation has no sense. marci@335: /// Let we stand one more example here to simplify your work. marci@335: /// wrapper class marci@335: /// \code template class RevGraphWrapper; \endcode marci@335: /// has constructor alpar@344: /// RevGraphWrapper(Graph& _g). marci@335: /// This means that in a situation, alpar@344: /// when a const ListGraph& reference to a graph is given, alpar@344: /// then it have to be instantiated with Graph=const ListGraph. marci@335: /// \code marci@335: /// int algorithm1(const ListGraph& g) { marci@335: /// RevGraphWrapper rgw(g); marci@335: /// return algorithm2(rgw); marci@335: /// } marci@335: /// \endcode marci@303: template marci@303: class GraphWrapper { marci@212: protected: marci@303: Graph* graph; marci@212: marci@212: public: marci@311: typedef Graph BaseGraph; marci@303: typedef Graph ParentGraph; marci@212: marci@303: // GraphWrapper() : graph(0) { } marci@303: GraphWrapper(Graph& _graph) : graph(&_graph) { } marci@303: // void setGraph(Graph& _graph) { graph=&_graph; } marci@303: // Graph& getGraph() const { return *graph; } marci@303: marci@317: // typedef typename Graph::Node Node; marci@317: class Node : public Graph::Node { marci@317: friend class GraphWrapper; marci@265: public: marci@317: Node() { } marci@317: Node(const typename Graph::Node& _n) : Graph::Node(_n) { } marci@317: Node(const Invalid& i) : Graph::Node(i) { } marci@317: }; marci@317: class NodeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::NodeIt n; marci@317: public: marci@265: NodeIt() { } marci@317: NodeIt(const typename Graph::NodeIt& _n) : n(_n) { } marci@317: NodeIt(const Invalid& i) : n(i) { } marci@317: NodeIt(const GraphWrapper& _G) : n(*(_G.graph)) { } marci@317: operator Node() const { return Node(typename Graph::Node(n)); } marci@265: }; marci@317: // typedef typename Graph::Edge Edge; marci@317: class Edge : public Graph::Edge { marci@317: friend class GraphWrapper; marci@317: public: marci@317: Edge() { } marci@317: Edge(const typename Graph::Edge& _e) : Graph::Edge(_e) { } marci@317: Edge(const Invalid& i) : Graph::Edge(i) { } marci@317: }; marci@317: class OutEdgeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::OutEdgeIt e; marci@265: public: marci@265: OutEdgeIt() { } marci@317: OutEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@317: OutEdgeIt(const Invalid& i) : e(i) { } marci@317: OutEdgeIt(const GraphWrapper& _G, const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@265: }; marci@317: class InEdgeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::InEdgeIt e; marci@265: public: marci@265: InEdgeIt() { } marci@317: InEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@317: InEdgeIt(const Invalid& i) : e(i) { } marci@317: InEdgeIt(const GraphWrapper& _G, const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@265: }; marci@303: //typedef typename Graph::SymEdgeIt SymEdgeIt; marci@317: class EdgeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::EdgeIt e; marci@265: public: marci@265: EdgeIt() { } marci@317: EdgeIt(const typename Graph::EdgeIt& _e) : e(_e) { } marci@317: EdgeIt(const Invalid& i) : e(i) { } marci@317: EdgeIt(const GraphWrapper& _G) : e(*(_G.graph)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@265: }; marci@303: marci@303: NodeIt& first(NodeIt& i) const { marci@317: i=NodeIt(*this); return i; marci@265: } marci@303: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@303: } marci@303: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@303: } marci@311: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@311: } marci@338: marci@317: NodeIt& next(NodeIt& i) const { graph->next(i.n); return i; } marci@317: OutEdgeIt& next(OutEdgeIt& i) const { graph->next(i.e); return i; } marci@317: InEdgeIt& next(InEdgeIt& i) const { graph->next(i.e); return i; } marci@317: EdgeIt& next(EdgeIt& i) const { graph->next(i.e); return i; } marci@212: marci@379: Node tail(const Edge& e) const { marci@379: return Node(graph->tail(static_cast(e))); } marci@317: Node head(const Edge& e) const { marci@317: return Node(graph->head(static_cast(e))); } marci@212: marci@317: bool valid(const Node& n) const { marci@317: return graph->valid(static_cast(n)); } marci@317: bool valid(const Edge& e) const { marci@317: return graph->valid(static_cast(e)); } marci@212: marci@303: int nodeNum() const { return graph->nodeNum(); } marci@303: int edgeNum() const { return graph->edgeNum(); } marci@212: marci@317: Node aNode(const OutEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@317: Node aNode(const InEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@317: Node bNode(const OutEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@317: Node bNode(const InEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@212: marci@317: Node addNode() const { return Node(graph->addNode()); } marci@212: Edge addEdge(const Node& tail, const Node& head) const { marci@317: return Edge(graph->addEdge(tail, head)); } marci@317: marci@317: void erase(const Node& i) const { graph->erase(i); } marci@317: void erase(const Edge& i) const { graph->erase(i); } marci@212: marci@303: void clear() const { graph->clear(); } marci@212: marci@303: template class NodeMap : public Graph::NodeMap { marci@212: public: marci@303: NodeMap(const GraphWrapper& _G) : marci@303: Graph::NodeMap(*(_G.graph)) { } marci@303: NodeMap(const GraphWrapper& _G, T a) : marci@303: Graph::NodeMap(*(_G.graph), a) { } marci@212: }; marci@212: marci@303: template class EdgeMap : public Graph::EdgeMap { marci@212: public: marci@303: EdgeMap(const GraphWrapper& _G) : marci@303: Graph::EdgeMap(*(_G.graph)) { } marci@303: EdgeMap(const GraphWrapper& _G, T a) : marci@303: Graph::EdgeMap(*(_G.graph), a) { } marci@212: }; marci@212: }; marci@212: marci@338: /// A graph wrapper which reverses the orientation of the edges. marci@303: marci@338: /// A graph wrapper which reverses the orientation of the edges. marci@303: template marci@303: class RevGraphWrapper : public GraphWrapper { marci@230: public: marci@338: marci@338: RevGraphWrapper(Graph& _graph) : GraphWrapper(_graph) { } marci@338: marci@303: typedef typename GraphWrapper::Node Node; marci@303: typedef typename GraphWrapper::Edge Edge; marci@303: //If Graph::OutEdgeIt is not defined marci@279: //and we do not want to use RevGraphWrapper::InEdgeIt, marci@338: //the typdef techinque does not work. marci@338: //Unfortunately all the typedefs are instantiated in templates. marci@338: //typedef typename GraphWrapper::OutEdgeIt InEdgeIt; marci@338: //typedef typename GraphWrapper::InEdgeIt OutEdgeIt; marci@237: marci@338: class OutEdgeIt { marci@338: friend class GraphWrapper; marci@338: friend class RevGraphWrapper; marci@379: typename Graph::InEdgeIt e; marci@338: public: marci@338: OutEdgeIt() { } marci@379: OutEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@338: OutEdgeIt(const Invalid& i) : e(i) { } marci@338: OutEdgeIt(const RevGraphWrapper& _G, const Node& _n) : marci@338: e(*(_G.graph), typename Graph::Node(_n)) { } marci@338: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@338: }; marci@338: class InEdgeIt { marci@338: friend class GraphWrapper; marci@338: friend class RevGraphWrapper; marci@379: typename Graph::OutEdgeIt e; marci@338: public: marci@338: InEdgeIt() { } marci@379: InEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@338: InEdgeIt(const Invalid& i) : e(i) { } marci@338: InEdgeIt(const RevGraphWrapper& _G, const Node& _n) : marci@338: e(*(_G.graph), typename Graph::Node(_n)) { } marci@338: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@338: }; marci@238: marci@338: using GraphWrapper::first; marci@338: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@338: i=OutEdgeIt(*this, p); return i; marci@338: } marci@338: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@338: i=InEdgeIt(*this, p); return i; marci@338: } marci@338: marci@338: using GraphWrapper::next; marci@338: OutEdgeIt& next(OutEdgeIt& i) const { graph->next(i.e); return i; } marci@338: InEdgeIt& next(InEdgeIt& i) const { graph->next(i.e); return i; } marci@338: marci@338: Node aNode(const OutEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@338: Node aNode(const InEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@338: Node bNode(const OutEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@338: Node bNode(const InEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@379: marci@379: Node tail(const Edge& e) const { marci@379: return GraphWrapper::head(e); } marci@379: Node head(const Edge& e) const { marci@379: return GraphWrapper::tail(e); } marci@379: marci@76: }; marci@76: marci@335: /// Wrapper for hiding nodes and edges from a graph. marci@335: marci@335: /// This wrapper shows a graph with filtered node-set and klao@363: /// edge-set. The quick brown fox iterator jumps over marci@335: /// the lazy dog nodes or edges if the values for them are false marci@335: /// in the bool maps. marci@311: template marci@303: class SubGraphWrapper : public GraphWrapper { marci@263: protected: marci@311: NodeFilterMap* node_filter_map; marci@311: EdgeFilterMap* edge_filter_map; marci@263: public: marci@338: marci@311: SubGraphWrapper(Graph& _graph, NodeFilterMap& _node_filter_map, marci@311: EdgeFilterMap& _edge_filter_map) : marci@311: GraphWrapper(_graph), node_filter_map(&_node_filter_map), marci@311: edge_filter_map(&_edge_filter_map) { } marci@263: marci@317: typedef typename GraphWrapper::Node Node; marci@317: class NodeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::NodeIt n; marci@317: public: marci@311: NodeIt() { } marci@317: NodeIt(const typename Graph::NodeIt& _n) : n(_n) { } marci@317: NodeIt(const Invalid& i) : n(i) { } marci@311: NodeIt(const SubGraphWrapper& _G) : marci@317: n(*(_G.graph)) { marci@317: while (_G.graph->valid(n) && !(*(_G.node_filter_map))[n]) marci@317: _G.graph->next(n); marci@311: } marci@317: operator Node() const { return Node(typename Graph::Node(n)); } marci@311: }; marci@317: typedef typename GraphWrapper::Edge Edge; marci@317: class OutEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::OutEdgeIt e; marci@311: public: marci@311: OutEdgeIt() { } marci@317: OutEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@317: OutEdgeIt(const Invalid& i) : e(i) { } marci@317: OutEdgeIt(const SubGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { marci@317: while (_G.graph->valid(e) && !(*(_G.edge_filter_map))[e]) marci@317: _G.graph->next(e); marci@311: } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: class InEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::InEdgeIt e; marci@311: public: marci@311: InEdgeIt() { } marci@317: InEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@317: InEdgeIt(const Invalid& i) : e(i) { } marci@311: InEdgeIt(const SubGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { marci@317: while (_G.graph->valid(e) && !(*(_G.edge_filter_map))[e]) marci@317: _G.graph->next(e); marci@311: } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: //typedef typename Graph::SymEdgeIt SymEdgeIt; marci@317: class EdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::EdgeIt e; marci@311: public: marci@311: EdgeIt() { } marci@317: EdgeIt(const typename Graph::EdgeIt& _e) : e(_e) { } marci@317: EdgeIt(const Invalid& i) : e(i) { } marci@311: EdgeIt(const SubGraphWrapper& _G) : marci@317: e(*(_G.graph)) { marci@317: while (_G.graph->valid(e) && !(*(_G.edge_filter_map))[e]) marci@317: _G.graph->next(e); marci@311: } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: marci@317: NodeIt& first(NodeIt& i) const { marci@317: i=NodeIt(*this); return i; marci@263: } marci@317: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@311: } marci@317: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@311: } marci@317: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@263: } marci@263: marci@311: NodeIt& next(NodeIt& i) const { marci@317: graph->next(i.n); marci@317: while (graph->valid(i) && !(*node_filter_map)[i.n]) { graph->next(i.n); } marci@311: return i; marci@311: } marci@311: OutEdgeIt& next(OutEdgeIt& i) const { marci@317: graph->next(i.e); marci@317: while (graph->valid(i) && !(*edge_filter_map)[i.e]) { graph->next(i.e); } marci@311: return i; marci@311: } marci@311: InEdgeIt& next(InEdgeIt& i) const { marci@317: graph->next(i.e); marci@317: while (graph->valid(i) && !(*edge_filter_map)[i.e]) { graph->next(i.e); } marci@311: return i; marci@311: } marci@311: EdgeIt& next(EdgeIt& i) const { marci@317: graph->next(i.e); marci@317: while (graph->valid(i) && !(*edge_filter_map)[i.e]) { graph->next(i.e); } marci@311: return i; marci@311: } marci@311: marci@323: Node aNode(const OutEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@323: Node aNode(const InEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@323: Node bNode(const OutEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@323: Node bNode(const InEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@323: alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void hide(const Node& n) const { node_filter_map->set(n, false); } alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void hide(const Edge& e) const { edge_filter_map->set(e, false); } marci@323: alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void unHide(const Node& n) const { node_filter_map->set(n, true); } alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void unHide(const Edge& e) const { edge_filter_map->set(e, true); } marci@323: alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: bool hidden(const Node& n) const { return (*node_filter_map)[n]; } alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: bool hidden(const Edge& e) const { return (*edge_filter_map)[e]; } marci@263: }; marci@155: alpar@356: /// A wrapper for forgetting the orientation of a graph. marci@317: alpar@356: /// A wrapper for getting an undirected graph by forgetting alpar@356: /// the orientation of a directed one. marci@303: template marci@303: class UndirGraphWrapper : public GraphWrapper { marci@303: public: marci@303: typedef typename GraphWrapper::Node Node; marci@303: typedef typename GraphWrapper::NodeIt NodeIt; marci@317: typedef typename GraphWrapper::Edge Edge; marci@317: typedef typename GraphWrapper::EdgeIt EdgeIt; marci@236: marci@303: UndirGraphWrapper(Graph& _graph) : GraphWrapper(_graph) { } marci@158: marci@317: class OutEdgeIt { marci@303: friend class UndirGraphWrapper; marci@158: bool out_or_in; //true iff out marci@317: typename Graph::OutEdgeIt out; marci@317: typename Graph::InEdgeIt in; marci@158: public: marci@317: OutEdgeIt() { } marci@317: OutEdgeIt(const Invalid& i) : Edge(i) { } marci@317: OutEdgeIt(const UndirGraphWrapper& _G, const Node& _n) { marci@317: out_or_in=true; _G.graph->first(out, _n); marci@317: if (!(_G.graph->valid(out))) { out_or_in=false; _G.graph->first(in, _n); } marci@174: } marci@317: operator Edge() const { marci@317: if (out_or_in) return Edge(out); else return Edge(in); marci@158: } marci@158: }; marci@158: marci@317: //FIXME InEdgeIt marci@238: typedef OutEdgeIt InEdgeIt; marci@238: marci@338: using GraphWrapper::first; marci@338: // NodeIt& first(NodeIt& i) const { marci@338: // i=NodeIt(*this); return i; marci@338: // } marci@317: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@317: } marci@317: //FIXME marci@317: // InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: // i=InEdgeIt(*this, p); return i; marci@317: // } marci@338: // EdgeIt& first(EdgeIt& i) const { marci@338: // i=EdgeIt(*this); return i; marci@338: // } marci@238: marci@338: using GraphWrapper::next; marci@338: // NodeIt& next(NodeIt& n) const { marci@338: // GraphWrapper::next(n); marci@338: // return n; marci@338: // } marci@158: OutEdgeIt& next(OutEdgeIt& e) const { marci@158: if (e.out_or_in) { marci@317: typename Graph::Node n=graph->tail(e.out); marci@303: graph->next(e.out); marci@303: if (!graph->valid(e.out)) { e.out_or_in=false; graph->first(e.in, n); } marci@158: } else { marci@303: graph->next(e.in); marci@158: } marci@158: return e; marci@158: } marci@317: //FIXME InEdgeIt marci@338: // EdgeIt& next(EdgeIt& e) const { marci@338: // GraphWrapper::next(n); marci@338: // // graph->next(e.e); marci@338: // return e; marci@338: // } marci@238: marci@238: Node aNode(const OutEdgeIt& e) const { marci@303: if (e.out_or_in) return graph->tail(e); else return graph->head(e); } marci@238: Node bNode(const OutEdgeIt& e) const { marci@303: if (e.out_or_in) return graph->head(e); else return graph->tail(e); } marci@338: }; marci@158: marci@338: /// A wrapper for composing the residual graph for directed flow and circulation problems. marci@238: marci@338: /// A wrapper for composing the residual graph for directed flow and circulation problems. marci@330: template marci@311: class ResGraphWrapper : public GraphWrapper { marci@199: protected: marci@330: const CapacityMap* capacity; marci@155: FlowMap* flow; marci@155: public: marci@168: marci@330: ResGraphWrapper(Graph& _graph, const CapacityMap& _capacity, marci@330: FlowMap& _flow) : marci@330: GraphWrapper(_graph), capacity(&_capacity), flow(&_flow) { } marci@168: marci@174: class Edge; marci@155: class OutEdgeIt; marci@174: friend class Edge; marci@155: friend class OutEdgeIt; marci@76: marci@311: typedef typename GraphWrapper::Node Node; marci@311: typedef typename GraphWrapper::NodeIt NodeIt; marci@317: class Edge : public Graph::Edge { marci@330: friend class ResGraphWrapper; marci@155: protected: marci@317: bool forward; //true, iff forward marci@317: // typename Graph::Edge e; marci@155: public: marci@317: Edge() { } marci@317: Edge(const typename Graph::Edge& _e, bool _forward) : marci@317: Graph::Edge(_e), forward(_forward) { } marci@317: Edge(const Invalid& i) : Graph::Edge(i), forward(false) { } marci@317: //the unique invalid iterator marci@174: friend bool operator==(const Edge& u, const Edge& v) { marci@317: return (v.forward==u.forward && marci@317: static_cast(u)== marci@317: static_cast(v)); marci@174: } marci@174: friend bool operator!=(const Edge& u, const Edge& v) { marci@317: return (v.forward!=u.forward || marci@317: static_cast(u)!= marci@317: static_cast(v)); marci@174: } marci@155: }; marci@338: marci@317: class OutEdgeIt { marci@330: friend class ResGraphWrapper; marci@317: protected: marci@317: typename Graph::OutEdgeIt out; marci@317: typename Graph::InEdgeIt in; marci@317: bool forward; marci@155: public: marci@155: OutEdgeIt() { } marci@168: //FIXME marci@317: // OutEdgeIt(const Edge& e) : Edge(e) { } marci@317: OutEdgeIt(const Invalid& i) : out(i), in(i), forward(false) { } marci@317: //the unique invalid iterator marci@330: OutEdgeIt(const ResGraphWrapper& resG, Node v) { marci@317: forward=true; marci@303: resG.graph->first(out, v); marci@317: while( resG.graph->valid(out) && !(resG.resCap(*this)>0) ) { resG.graph->next(out); } marci@303: if (!resG.graph->valid(out)) { marci@317: forward=false; marci@303: resG.graph->first(in, v); marci@317: while( resG.graph->valid(in) && !(resG.resCap(*this)>0) ) { resG.graph->next(in); } marci@155: } marci@155: } marci@317: operator Edge() const { marci@317: // Edge e; marci@317: // e.forward=this->forward; marci@317: // if (this->forward) e=out; else e=in; marci@317: // return e; marci@317: if (this->forward) marci@317: return Edge(out, this->forward); marci@317: else marci@317: return Edge(in, this->forward); marci@317: } marci@317: }; marci@263: marci@317: class InEdgeIt { marci@330: friend class ResGraphWrapper; marci@317: protected: marci@317: typename Graph::OutEdgeIt out; marci@317: typename Graph::InEdgeIt in; marci@317: bool forward; marci@317: public: marci@317: InEdgeIt() { } marci@317: //FIXME marci@317: // OutEdgeIt(const Edge& e) : Edge(e) { } marci@317: InEdgeIt(const Invalid& i) : out(i), in(i), forward(false) { } marci@317: //the unique invalid iterator marci@330: InEdgeIt(const ResGraphWrapper& resG, Node v) { marci@317: forward=true; marci@317: resG.graph->first(in, v); marci@317: while( resG.graph->valid(in) && !(resG.resCap(*this)>0) ) { resG.graph->next(in); } marci@317: if (!resG.graph->valid(in)) { marci@317: forward=false; marci@317: resG.graph->first(out, v); marci@317: while( resG.graph->valid(out) && !(resG.resCap(*this)>0) ) { resG.graph->next(out); } marci@317: } marci@317: } marci@317: operator Edge() const { marci@317: // Edge e; marci@317: // e.forward=this->forward; marci@317: // if (this->forward) e=out; else e=in; marci@317: // return e; marci@317: if (this->forward) marci@317: return Edge(in, this->forward); marci@317: else marci@317: return Edge(out, this->forward); marci@317: } marci@317: }; marci@317: marci@317: class EdgeIt { marci@330: friend class ResGraphWrapper; marci@317: protected: marci@317: typename Graph::EdgeIt e; marci@317: bool forward; marci@155: public: marci@174: EdgeIt() { } marci@317: EdgeIt(const Invalid& i) : e(i), forward(false) { } marci@330: EdgeIt(const ResGraphWrapper& resG) { marci@317: forward=true; marci@317: resG.graph->first(e); marci@317: while (resG.graph->valid(e) && !(resG.resCap(*this)>0)) resG.graph->next(e); marci@317: if (!resG.graph->valid(e)) { marci@317: forward=false; marci@317: resG.graph->first(e); marci@317: while (resG.graph->valid(e) && !(resG.resCap(*this)>0)) resG.graph->next(e); marci@155: } marci@155: } marci@317: operator Edge() const { marci@317: return Edge(e, this->forward); marci@317: } marci@317: }; marci@155: marci@338: using GraphWrapper::first; marci@338: // NodeIt& first(NodeIt& i) const { marci@338: // i=NodeIt(*this); return i; marci@338: // } marci@311: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@311: } marci@317: // FIXME not tested marci@317: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@317: } marci@317: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@155: } marci@338: marci@338: using GraphWrapper::next; marci@338: // NodeIt& next(NodeIt& n) const { GraphWrapper::next(n); return n; } marci@155: OutEdgeIt& next(OutEdgeIt& e) const { marci@317: if (e.forward) { marci@303: Node v=graph->aNode(e.out); marci@303: graph->next(e.out); marci@317: while( graph->valid(e.out) && !(resCap(e)>0) ) { graph->next(e.out); } marci@303: if (!graph->valid(e.out)) { marci@317: e.forward=false; marci@303: graph->first(e.in, v); marci@317: while( graph->valid(e.in) && !(resCap(e)>0) ) { graph->next(e.in); } marci@155: } marci@155: } else { marci@303: graph->next(e.in); marci@317: while( graph->valid(e.in) && !(resCap(e)>0) ) { graph->next(e.in); } marci@155: } marci@155: return e; marci@155: } marci@317: // FIXME Not tested marci@317: InEdgeIt& next(InEdgeIt& e) const { marci@317: if (e.forward) { marci@317: Node v=graph->aNode(e.in); marci@317: graph->next(e.in); marci@317: while( graph->valid(e.in) && !(resCap(e)>0) ) { graph->next(e.in); } marci@317: if (!graph->valid(e.in)) { marci@317: e.forward=false; marci@317: graph->first(e.out, v); marci@317: while( graph->valid(e.out) && !(resCap(e)>0) ) { graph->next(e.out); } marci@317: } marci@317: } else { marci@303: graph->next(e.out); marci@317: while( graph->valid(e.out) && !(resCap(e)>0) ) { graph->next(e.out); } marci@317: } marci@317: return e; marci@317: } marci@317: EdgeIt& next(EdgeIt& e) const { marci@317: if (e.forward) { marci@317: graph->next(e.e); marci@317: while( graph->valid(e.e) && !(resCap(e)>0) ) { graph->next(e.e); } marci@317: if (!graph->valid(e.e)) { marci@317: e.forward=false; marci@317: graph->first(e.e); marci@317: while( graph->valid(e.e) && !(resCap(e)>0) ) { graph->next(e.e); } marci@155: } marci@317: } else { marci@317: graph->next(e.e); marci@317: while( graph->valid(e.e) && !(resCap(e)>0) ) { graph->next(e.e); } marci@155: } marci@317: return e; marci@317: } marci@76: marci@174: Node tail(Edge e) const { marci@317: return ((e.forward) ? graph->tail(e) : graph->head(e)); } marci@174: Node head(Edge e) const { marci@317: return ((e.forward) ? graph->head(e) : graph->tail(e)); } marci@76: marci@174: Node aNode(OutEdgeIt e) const { marci@317: return ((e.forward) ? graph->aNode(e.out) : graph->aNode(e.in)); } marci@174: Node bNode(OutEdgeIt e) const { marci@317: return ((e.forward) ? graph->bNode(e.out) : graph->bNode(e.in)); } marci@76: marci@376: Node aNode(InEdgeIt e) const { marci@376: return ((e.forward) ? graph->aNode(e.in) : graph->aNode(e.out)); } marci@376: Node bNode(InEdgeIt e) const { marci@376: return ((e.forward) ? graph->bNode(e.in) : graph->bNode(e.out)); } marci@376: marci@338: // int nodeNum() const { return graph->nodeNum(); } marci@263: //FIXME marci@338: void edgeNum() const { } marci@303: //int edgeNum() const { return graph->edgeNum(); } marci@263: marci@263: marci@317: // int id(Node v) const { return graph->id(v); } marci@155: marci@317: bool valid(Node n) const { return GraphWrapper::valid(n); } marci@174: bool valid(Edge e) const { marci@317: return graph->valid(e); marci@317: //return e.forward ? graph->valid(e.out) : graph->valid(e.in); marci@317: } marci@155: marci@174: void augment(const Edge& e, Number a) const { marci@317: if (e.forward) marci@303: // flow->set(e.out, flow->get(e.out)+a); marci@317: flow->set(e, (*flow)[e]+a); marci@168: else marci@303: // flow->set(e.in, flow->get(e.in)-a); marci@317: flow->set(e, (*flow)[e]-a); marci@168: } marci@168: marci@269: Number resCap(const Edge& e) const { marci@317: if (e.forward) marci@303: // return (capacity->get(e.out)-flow->get(e.out)); marci@317: return ((*capacity)[e]-(*flow)[e]); marci@168: else marci@303: // return (flow->get(e.in)); marci@317: return ((*flow)[e]); marci@168: } marci@168: marci@317: // Number resCap(typename Graph::OutEdgeIt out) const { marci@317: // // return (capacity->get(out)-flow->get(out)); marci@317: // return ((*capacity)[out]-(*flow)[out]); marci@317: // } marci@168: marci@317: // Number resCap(typename Graph::InEdgeIt in) const { marci@317: // // return (flow->get(in)); marci@317: // return ((*flow)[in]); marci@317: // } marci@168: marci@155: template marci@155: class EdgeMap { marci@303: typename Graph::EdgeMap forward_map, backward_map; marci@155: public: marci@330: EdgeMap(const ResGraphWrapper& _G) : forward_map(*(_G.graph)), backward_map(*(_G.graph)) { } marci@330: EdgeMap(const ResGraphWrapper& _G, T a) : forward_map(*(_G.graph), a), backward_map(*(_G.graph), a) { } marci@174: void set(Edge e, T a) { marci@317: if (e.forward) marci@155: forward_map.set(e.out, a); marci@155: else marci@155: backward_map.set(e.in, a); marci@155: } marci@303: T operator[](Edge e) const { marci@317: if (e.forward) marci@303: return forward_map[e.out]; marci@155: else marci@303: return backward_map[e.in]; marci@155: } marci@303: // T get(Edge e) const { marci@303: // if (e.out_or_in) marci@303: // return forward_map.get(e.out); marci@303: // else marci@303: // return backward_map.get(e.in); marci@303: // } marci@155: }; marci@168: }; marci@168: marci@338: /// ErasingFirstGraphWrapper for blocking flows. marci@317: marci@338: /// ErasingFirstGraphWrapper for blocking flows. marci@303: template marci@303: class ErasingFirstGraphWrapper : public GraphWrapper { marci@269: protected: marci@269: FirstOutEdgesMap* first_out_edges; marci@269: public: marci@303: ErasingFirstGraphWrapper(Graph& _graph, marci@303: FirstOutEdgesMap& _first_out_edges) : marci@303: GraphWrapper(_graph), first_out_edges(&_first_out_edges) { } marci@269: marci@317: typedef typename GraphWrapper::Node Node; marci@338: // class NodeIt { marci@338: // friend class GraphWrapper; marci@338: // friend class ErasingFirstGraphWrapper; marci@338: // typename Graph::NodeIt n; marci@338: // public: marci@338: // NodeIt() { } marci@338: // NodeIt(const typename Graph::NodeIt& _n) : n(_n) { } marci@338: // NodeIt(const Invalid& i) : n(i) { } marci@338: // NodeIt(const ErasingFirstGraphWrapper& _G) : marci@338: // n(*(_G.graph)) { } marci@338: // operator Node() const { return Node(typename Graph::Node(n)); } marci@338: // }; marci@317: typedef typename GraphWrapper::Edge Edge; marci@317: class OutEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class ErasingFirstGraphWrapper; marci@317: // typedef typename Graph::OutEdgeIt GraphOutEdgeIt; marci@317: typename Graph::OutEdgeIt e; marci@311: public: marci@311: OutEdgeIt() { } marci@317: OutEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@317: OutEdgeIt(const Invalid& i) : e(i) { } marci@311: OutEdgeIt(const ErasingFirstGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e((*_G.first_out_edges)[_n]) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: class InEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class ErasingFirstGraphWrapper; marci@317: // typedef typename Graph::InEdgeIt GraphInEdgeIt; marci@317: typename Graph::InEdgeIt e; marci@311: public: marci@311: InEdgeIt() { } marci@317: InEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@317: InEdgeIt(const Invalid& i) : e(i) { } marci@311: InEdgeIt(const ErasingFirstGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@311: //typedef typename Graph::SymEdgeIt SymEdgeIt; marci@317: class EdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class ErasingFirstGraphWrapper; marci@317: // typedef typename Graph::EdgeIt GraphEdgeIt; marci@317: typename Graph::EdgeIt e; marci@311: public: marci@311: EdgeIt() { } marci@317: EdgeIt(const typename Graph::EdgeIt& _e) : e(_e) { } marci@317: EdgeIt(const Invalid& i) : e(i) { } marci@311: EdgeIt(const ErasingFirstGraphWrapper& _G) : marci@317: e(*(_G.graph)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@311: marci@338: using GraphWrapper::first; marci@338: // NodeIt& first(NodeIt& i) const { marci@338: // i=NodeIt(*this); return i; marci@338: // } marci@317: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@269: } marci@317: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@311: } marci@317: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@311: } marci@311: marci@338: using GraphWrapper::next; marci@338: // NodeIt& next(NodeIt& i) const { graph->next(i.n); return i; } marci@317: OutEdgeIt& next(OutEdgeIt& i) const { graph->next(i.e); return i; } marci@317: InEdgeIt& next(InEdgeIt& i) const { graph->next(i.e); return i; } marci@317: EdgeIt& next(EdgeIt& i) const { graph->next(i.e); return i; } marci@317: marci@317: Node aNode(const OutEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@317: Node aNode(const InEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@317: Node bNode(const OutEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@317: Node bNode(const InEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@311: marci@269: void erase(const OutEdgeIt& e) const { marci@269: OutEdgeIt f=e; marci@269: this->next(f); marci@317: first_out_edges->set(this->tail(e), f.e); marci@269: } marci@269: }; marci@269: marci@368: /// A wrapper for composing a bipartite graph. marci@371: /// \c _graph have to be a reference to a graph of type \c Graph marci@371: /// and \c _s_false_t_true_map is an \c IterableBoolMap marci@368: /// reference containing the elements for the marci@371: /// color classes S and T. \c _graph is to be referred to an undirected marci@371: /// graph or a directed graph with edges oriented from S to T. marci@368: template marci@368: class BipartiteGraphWrapper : public GraphWrapper { marci@368: typedef IterableBoolMap< typename Graph::NodeMap > SFalseTTrueMap; marci@368: SFalseTTrueMap* s_false_t_true_map; marci@368: marci@368: public: marci@379: static const bool S_CLASS=false; marci@379: static const bool T_CLASS=true; marci@379: marci@368: BipartiteGraphWrapper(Graph& _graph, SFalseTTrueMap& _s_false_t_true_map) marci@368: : GraphWrapper(_graph), s_false_t_true_map(&_s_false_t_true_map) { marci@368: } marci@368: typedef typename GraphWrapper::Node Node; marci@368: //using GraphWrapper::NodeIt; marci@368: typedef typename GraphWrapper::Edge Edge; marci@368: //using GraphWrapper::EdgeIt; marci@379: class ClassNodeIt { marci@368: Node n; marci@368: public: marci@379: ClassNodeIt() { } marci@379: ClassNodeIt(const Invalid& i) : n(i) { } marci@379: ClassNodeIt(const BipartiteGraphWrapper& _G, bool _class) { marci@379: _G.s_false_t_true_map->first(n, _class); marci@368: } marci@368: operator Node() const { return n; } marci@368: }; marci@379: // class SNodeIt { marci@379: // Node n; marci@379: // public: marci@379: // SNodeIt() { } marci@379: // SNodeIt(const Invalid& i) : n(i) { } marci@379: // SNodeIt(const BipartiteGraphWrapper& _G) { marci@379: // _G.s_false_t_true_map->first(n, false); marci@379: // } marci@379: // operator Node() const { return n; } marci@379: // }; marci@379: // class TNodeIt { marci@379: // Node n; marci@379: // public: marci@379: // TNodeIt() { } marci@379: // TNodeIt(const Invalid& i) : n(i) { } marci@379: // TNodeIt(const BipartiteGraphWrapper& _G) { marci@379: // _G.s_false_t_true_map->first(n, true); marci@379: // } marci@379: // operator Node() const { return n; } marci@379: // }; marci@368: class OutEdgeIt { marci@368: public: marci@379: marci@368: typename Graph::OutEdgeIt e; marci@368: public: marci@368: OutEdgeIt() { } marci@368: OutEdgeIt(const Invalid& i) : e(i) { } marci@368: OutEdgeIt(const BipartiteGraphWrapper& _G, const Node& _n) { marci@368: if (!(*(_G.s_false_t_true_map))[_n]) marci@379: e=typename Graph::OutEdgeIt(*(_G.graph), typename Graph::Node(_n)); marci@368: else marci@368: e=INVALID; marci@368: } marci@368: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@368: }; marci@368: class InEdgeIt { marci@368: public: marci@368: typename Graph::InEdgeIt e; marci@368: public: marci@368: InEdgeIt() { } marci@368: InEdgeIt(const Invalid& i) : e(i) { } marci@368: InEdgeIt(const BipartiteGraphWrapper& _G, const Node& _n) { marci@368: if ((*(_G.s_false_t_true_map))[_n]) marci@379: e=typename Graph::InEdgeIt(*(_G.graph), typename Graph::Node(_n)); marci@368: else marci@368: e=INVALID; marci@368: } marci@368: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@368: }; marci@368: marci@368: using GraphWrapper::first; marci@379: ClassNodeIt& first(ClassNodeIt& n, bool _class) const { marci@379: n=SNodeIt(*this, _class) ; return n; } marci@379: // SNodeIt& first(SNodeIt& n) const { n=SNodeIt(*this); return n; } marci@379: // TNodeIt& first(TNodeIt& n) const { n=TNodeIt(*this); return n; } marci@379: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@379: i=OutEdgeIt(*this, p); return i; marci@379: } marci@379: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@379: i=InEdgeIt(*this, p); return i; marci@379: } marci@368: marci@368: using GraphWrapper::next; marci@379: ClassNodeIt& next(ClassNodeIt& n) const { marci@368: this->s_false_t_true_map->next(n); return n; marci@368: } marci@379: // SNodeIt& next(SNodeIt& n) const { marci@379: // this->s_false_t_true_map->next(n); return n; marci@379: // } marci@379: // TNodeIt& next(TNodeIt& n) const { marci@379: // this->s_false_t_true_map->next(n); return n; marci@379: // } marci@379: OutEdgeIt& next(OutEdgeIt& i) const { graph->next(i.e); return i; } marci@379: InEdgeIt& next(InEdgeIt& i) const { graph->next(i.e); return i; } marci@368: marci@368: Node tail(const Edge& e) { marci@368: if (!(*(this->s_false_t_true_map))[this->graph->tail(e)]) marci@368: return Node(this->graph->tail(e)); marci@368: else marci@368: return Node(this->graph->head(e)); marci@368: } marci@368: Node head(const Edge& e) { marci@368: if (!(*(this->s_false_t_true_map))[this->graph->tail(e)]) marci@368: return Node(this->graph->head(e)); marci@368: else marci@368: return Node(this->graph->tail(e)); marci@368: } marci@368: marci@368: Node aNode(const OutEdgeIt& e) const { marci@368: return Node(this->graph->aNode(e.e)); marci@368: } marci@368: Node aNode(const InEdgeIt& e) const { marci@368: return Node(this->graph->aNode(e.e)); marci@368: } marci@368: Node bNode(const OutEdgeIt& e) const { marci@368: return Node(this->graph->bNode(e.e)); marci@368: } marci@368: Node bNode(const InEdgeIt& e) const { marci@368: return Node(this->graph->bNode(e.e)); marci@368: } marci@379: marci@379: bool inSClass(const Node& n) const { marci@379: return !(this->s_false_t_true_map[n]); marci@379: } marci@379: bool inTClass(const Node& n) const { marci@379: return (this->s_false_t_true_map[n]); marci@379: } marci@368: }; marci@368: marci@341: marci@379: /// experimentral, do not try it. marci@379: /// It eats a bipartite graph, oriented from S to T. marci@379: /// Such one can be made e.g. by the above wrapper. marci@379: template marci@379: class stGraphWrapper : public GraphWrapper { marci@379: public: marci@379: class Node; marci@379: //GN, int marci@379: //0 normalis, 1 s, 2, true, ez az iteralasi sorrend, marci@379: //es a vege a false azaz (invalid, 3) marci@379: class NodeIt; marci@379: //GNI, int marci@379: class Edge; marci@379: //GE, int, GN marci@379: //0 normalis, 1 s->vmi, 2 vmi->t, ez a sorrend, marci@379: //invalid: (invalid, 3, invalid) marci@379: class OutEdgeIt; marci@379: //GO, int, GNI marci@379: //normalis pontbol (first, 0, invalid), ..., (invalid, 2, vmi), ... (invalid, 3, invalid) marci@379: //s-bol (invalid, 1, first), ... (invalid, 3, invalid) marci@379: //t-bol (invalid, 3, invalid) marci@379: class InEdgeIt; marci@379: //GI, int, GNI marci@379: //normalis pontbol (first, 0, invalid), ..., (invalid, 1, vmi), ... (invalid, 3, invalid) marci@379: //s-be (invalid, 3, invalid) marci@379: //t-be (invalid, 2, first), ... (invalid, 3, invalid) marci@379: class EdgeIt; marci@379: //(first, 0, invalid) ... marci@379: //(invalid, 1, vmi) marci@379: //(invalid, 2, vmi) marci@379: //invalid, 3, invalid) marci@379: template class NodeMap; marci@379: template class EdgeMap; marci@341: marci@379: // template friend class NodeMap; marci@379: // template friend class EdgeMap; marci@341: marci@379: const Node S_NODE; marci@379: const Node T_NODE; marci@341: marci@379: static const bool S_CLASS=false; marci@379: static const bool T_CLASS=true; marci@341: marci@379: stGraphWrapper(Graph& _graph) : GraphWrapper(_graph) , marci@379: S_NODE(INVALID, 1), marci@379: T_NODE(INVALID, 2) { } marci@341: marci@379: class Node : public Graph::Node { marci@379: protected: marci@379: friend class GraphWrapper; marci@379: friend class stGraphWrapper; marci@379: template friend class stGraphWrapper::NodeMap; marci@380: friend class Edge; marci@380: friend class OutEdgeIt; marci@380: friend class InEdgeIt; marci@380: friend class EdgeIt; marci@379: int spec; marci@379: public: marci@379: Node() { } marci@379: Node(const typename Graph::Node& _n, int _spec=0) : marci@379: Graph::Node(_n), spec(_spec) { } marci@379: Node(const Invalid& i) : Graph::Node(i), spec(3) { } marci@379: friend bool operator==(const Node& u, const Node& v) { marci@379: return (u.spec==v.spec && marci@379: static_cast(u)== marci@379: static_cast(v)); marci@379: } marci@379: friend bool operator!=(const Node& u, const Node& v) { marci@379: return (v.spec!=u.spec || marci@379: static_cast(u)!= marci@379: static_cast(v)); marci@379: } marci@379: int getSpec() const { return spec; } marci@379: }; marci@379: class NodeIt { marci@379: friend class GraphWrapper; marci@379: friend class stGraphWrapper; marci@379: typename Graph::NodeIt n; marci@379: int spec; marci@379: public: marci@379: NodeIt() { } marci@379: NodeIt(const typename Graph::NodeIt& _n, int _spec) : marci@379: n(_n), spec(_spec) { } marci@379: NodeIt(const Invalid& i) : n(i), spec(3) { } marci@379: NodeIt(const GraphWrapper& _G) : n(*(_G.graph)), spec(0) { marci@379: if (!_G->valid(n)) spec=1; marci@379: } marci@379: operator Node() const { return Node(n, spec); } marci@379: }; marci@379: class Edge : public Graph::Edge { marci@379: friend class GraphWrapper; marci@379: friend class stGraphWrapper; marci@379: template friend class stGraphWrapper::EdgeMap; marci@379: int spec; marci@379: typename Graph::Node n; marci@379: public: marci@379: Edge() { } marci@379: Edge(const typename Graph::Edge& _e, int _spec, marci@379: const typename Graph::Node& _n) : marci@379: Graph::Edge(_e), spec(_spec), n(_n) { marci@379: } marci@379: Edge(const Invalid& i) : Graph::Edge(i), spec(3), n(i) { } marci@379: friend bool operator==(const Edge& u, const Edge& v) { marci@379: return (u.spec==v.spec && marci@379: static_cast(u)== marci@379: static_cast(v) && marci@379: u.n==v.n); marci@379: } marci@379: friend bool operator!=(const Edge& u, const Edge& v) { marci@379: return (v.spec!=u.spec || marci@379: static_cast(u)!= marci@379: static_cast(v) || marci@379: u.n!=v.n); marci@379: } marci@379: int getSpec() const { return spec; } marci@379: }; marci@379: class OutEdgeIt { marci@379: friend class GraphWrapper; marci@379: friend class stGraphWrapper; marci@379: typename Graph::OutEdgeIt e; marci@379: int spec; marci@379: typename Graph::ClassNodeIt n; marci@379: public: marci@379: OutEdgeIt() { } marci@379: OutEdgeIt(const typename Graph::OutEdgeIt& _e, int _spec, marci@379: const typename Graph::ClassNodeIt& _n) : marci@379: e(_e), spec(_spec), n(_n) { marci@379: } marci@379: OutEdgeIt(const Invalid& i) : e(i), spec(3), n(i) { } marci@379: OutEdgeIt(const GraphWrapper& _G, const Node& _n) { marci@379: switch (_n.spec) { marci@379: case 0 : marci@379: if (_G.graph->inSClass) { //S, van normalis kiel marci@379: e=typename Graph::OutEdgeIt(*(_G.graph), marci@379: typename Graph::Node(_n)); marci@379: spec=0; marci@379: n=INVALID; marci@379: if (!_G.graph->valid(e)) spec=3; marci@379: } else { //T, specko kiel van marci@379: e=INVALID; marci@379: spec=2; marci@379: n=_n; marci@379: } marci@379: break; marci@379: case 1: marci@379: e=INVALID; marci@379: spec=1; marci@379: _G.graph->first(n, S_CLASS); //s->vmi; marci@379: if (!_G.graph->valid(n)) spec=3; //Ha S ures marci@379: break; marci@379: case 2: marci@379: e=INVALID; marci@379: spec=3; marci@379: n=INVALID; marci@379: break; marci@379: } marci@379: } marci@379: operator Edge() const { return Edge(e, spec, n); } marci@379: }; marci@379: class InEdgeIt { marci@379: friend class GraphWrapper; marci@379: friend class stGraphWrapper; marci@379: typename Graph::InEdgeIt e; marci@379: int spec; marci@379: typename Graph::ClassNodeIt n; marci@379: public: marci@379: InEdgeIt() { } marci@379: InEdgeIt(const typename Graph::InEdgeIt& _e, int _spec, marci@379: const typename Graph::ClassNodeIt& _n) : marci@379: e(_e), spec(_spec), n(_n) { marci@379: } marci@379: InEdgeIt(const Invalid& i) : e(i), spec(3), n(i) { } marci@379: InEdgeIt(const GraphWrapper& _G, const Node& _n) { marci@379: switch (_n.spec) { marci@379: case 0 : marci@379: if (_G.graph->inTClass) { //T, van normalis beel marci@379: e=typename Graph::InEdgeIt(*(_G.graph), marci@379: typename Graph::Node(_n)); marci@379: spec=0; marci@379: n=INVALID; marci@379: if (!_G.graph->valid(e)) spec=3; marci@379: } else { //S, specko beel van marci@379: e=INVALID; marci@379: spec=1; marci@379: n=_n; marci@379: } marci@379: break; marci@379: case 1: marci@379: e=INVALID; marci@379: spec=3; marci@379: n=INVALID; marci@379: case 2: marci@379: e=INVALID; marci@379: spec=1; marci@379: _G.graph->first(n, T_CLASS); //vmi->t; marci@379: if (!_G.graph->valid(n)) spec=3; //Ha T ures marci@379: break; marci@379: } marci@379: } marci@379: operator Edge() const { return Edge(e, spec, n); } marci@379: }; marci@379: class EdgeIt { marci@379: friend class GraphWrapper; marci@379: friend class stGraphWrapper; marci@379: typename Graph::EdgeIt e; marci@379: int spec; marci@379: typename Graph::ClassNodeIt n; marci@379: public: marci@379: EdgeIt() { } marci@379: EdgeIt(const typename Graph::EdgeIt& _e, int _spec, marci@379: const typename Graph::ClassNodeIt& _n) : marci@379: e(_e), spec(_spec), n(_n) { } marci@379: EdgeIt(const Invalid& i) : e(i), spec(3), n(i) { } marci@379: EdgeIt(const GraphWrapper& _G) : marci@379: e(*(_G.graph)), spec(0), n(INVALID) { marci@379: if (!_G.graph->valid(e)) { marci@379: spec=1; marci@379: _G.graph->first(n, S_CLASS); marci@379: if (!_G.graph->valid(n)) { //Ha S ures marci@379: spec=2; marci@379: _G.graph->first(n, T_CLASS); marci@379: if (!_G.graph->valid(n)) { //Ha T ures marci@379: spec=3; marci@379: } marci@379: } marci@379: } marci@379: } marci@379: operator Edge() const { return Edge(e, spec, n); } marci@379: }; marci@341: marci@379: NodeIt& first(NodeIt& i) const { marci@379: i=NodeIt(*this); return i; marci@379: } marci@379: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@379: i=OutEdgeIt(*this, p); return i; marci@379: } marci@379: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@379: i=InEdgeIt(*this, p); return i; marci@379: } marci@379: EdgeIt& first(EdgeIt& i) const { marci@379: i=EdgeIt(*this); return i; marci@379: } marci@341: marci@379: NodeIt& next(NodeIt& i) const { marci@379: switch (i.spec) { marci@379: case 0: marci@379: graph->next(i.n); marci@379: if (!graph->valid(i.n)) { marci@379: i.spec=1; marci@379: } marci@379: break; marci@379: case 1: marci@379: i.spec=2; marci@379: break; marci@379: case 2: marci@379: i.spec=3; marci@379: break; marci@379: } marci@379: return i; marci@379: } marci@379: OutEdgeIt& next(OutEdgeIt& i) const { marci@379: switch (i.spec) { marci@379: case 0: //normal edge marci@379: typename Graph::Node v=graph->aNode(i.e); marci@379: graph->next(i.e); marci@379: if (!graph->valid(i.e)) { //Az igazi elek vegere ertunk marci@379: if (graph->inSClass(v)) { //S, nincs kiel marci@379: i.spec=3; marci@379: i.n=INVALID; marci@379: } else { //T, van kiel marci@379: i.spec=2; marci@379: i.n=v; marci@379: } marci@379: } marci@379: break; marci@379: case 1: //s->vmi marci@379: graph->next(i.n); marci@379: if (!graph->valid(i.n)) i.spec=3; marci@379: break; marci@379: case 2: //vmi->t marci@379: i.spec=3; marci@379: i.n=INVALID; marci@379: break; marci@379: } marci@379: return i; marci@379: } marci@379: InEdgeIt& next(InEdgeIt& i) const { marci@379: switch (i.spec) { marci@379: case 0: //normal edge marci@379: typename Graph::Node v=graph->aNode(i.e); marci@379: graph->next(i.e); marci@379: if (!graph->valid(i.e)) { //Az igazi elek vegere ertunk marci@379: if (graph->inTClass(v)) { //S, nincs beel marci@379: i.spec=3; marci@379: i.n=INVALID; marci@379: } else { //S, van beel marci@379: i.spec=1; marci@379: i.n=v; marci@379: } marci@379: } marci@379: break; marci@379: case 1: //s->vmi marci@379: i.spec=3; marci@379: i.n=INVALID; marci@379: break; marci@379: case 2: //vmi->t marci@379: graph->next(i.n); marci@379: if (!graph->valid(i.n)) i.spec=3; marci@379: break; marci@379: } marci@379: return i; marci@379: } marci@341: marci@379: EdgeIt& next(EdgeIt& i) const { marci@379: switch (i.spec) { marci@379: case 0: marci@379: graph->next(i.e); marci@379: if (!graph->valid(i.e)) { marci@379: i.spec=1; marci@379: graph->first(n, S_CLASS); marci@379: if (!graph->valid(i.n)) { marci@379: i.spec=2; marci@379: graph->first(n, T_CLASS); marci@379: if (!graph->valid(i.n)) spec=3; marci@379: } marci@379: } marci@379: break; marci@379: case 1: marci@379: graph->next(i.n); marci@379: if (!graph->valid(i.n)) { marci@379: i.spec=2; marci@379: graph->first(n, T_CLASS); marci@379: if (!graph->valid(i.n)) spec=3; marci@379: } marci@379: break; marci@379: case 2: marci@379: graph->next(i.n); marci@379: if (!graph->valid(i.n)) i.spec=3; marci@379: break; marci@379: } marci@379: return i; marci@379: } marci@341: marci@379: Node tail(const Edge& e) const { marci@379: switch (e.spec) { marci@379: case 0: marci@379: return Node(graph->tail(e)); marci@379: break; marci@379: case 1: marci@379: return S_NODE; marci@379: break; marci@379: case 2: marci@379: return Node(e.n); marci@379: break; marci@379: } marci@379: } marci@379: Node head(const Edge& e) const { marci@379: switch (e.spec) { marci@379: case 0: marci@379: return Node(graph->head(e)); marci@379: break; marci@379: case 1: marci@379: return Node(e.n); marci@379: break; marci@379: case 2: marci@379: return T_NODE; marci@379: break; marci@379: } marci@379: } marci@341: marci@379: bool valid(const Node& n) const { return (n.spec<3); } marci@379: bool valid(const Edge& e) const { return (e.spec<3); } marci@379: marci@379: // int nodeNum() const { return graph->nodeNum(); } marci@379: // int edgeNum() const { return graph->edgeNum(); } marci@341: marci@379: Node aNode(const OutEdgeIt& e) const { return tail(e); } marci@379: Node aNode(const InEdgeIt& e) const { return head(e); } marci@379: Node bNode(const OutEdgeIt& e) const { return head(e); } marci@379: Node bNode(const InEdgeIt& e) const { return tail(e); } marci@341: marci@379: // Node addNode() const { return Node(graph->addNode()); } marci@379: // Edge addEdge(const Node& tail, const Node& head) const { marci@379: // return Edge(graph->addEdge(tail, head)); } marci@341: marci@379: // void erase(const Node& i) const { graph->erase(i); } marci@379: // void erase(const Edge& i) const { graph->erase(i); } marci@341: marci@379: // void clear() const { graph->clear(); } marci@341: marci@379: template class NodeMap : public GraphWrapper::NodeMap { marci@379: T s_value, t_value; marci@379: public: marci@379: NodeMap(const stGraphWrapper& _G) : marci@379: GraphWrapper::NodeMap(_G) { } marci@379: NodeMap(const stGraphWrapper& _G, T a) : marci@379: GraphWrapper::NodeMap(_G, a), s_value(a), t_value(a) { } marci@379: T operator[](const Node& n) const { marci@379: switch (n.spec) { marci@379: case 0: marci@379: return (*this)[n]; marci@379: break; marci@379: case 1: marci@379: return s_value; marci@379: break; marci@379: case 2: marci@379: return t_value; marci@379: break; marci@379: } marci@379: } marci@379: void set(const Node& n, T t) { marci@379: switch (n.spec) { marci@379: case 0: marci@379: GraphWrapper::NodeMap::set(n, t); marci@379: break; marci@379: case 1: marci@379: s_value=t; marci@379: break; marci@379: case 2: marci@379: t_value=t; marci@379: break; marci@379: } marci@379: } marci@379: }; marci@341: marci@379: template class EdgeMap : public GraphWrapper::EdgeMap { marci@379: typename GraphWrapper::NodeMap node_value; marci@379: public: marci@379: EdgeMap(const stGraphWrapper& _G) : marci@379: GraphWrapper::EdgeMap(_G), node_value(_G) { } marci@379: EdgeMap(const stGraphWrapper& _G, T a) : marci@379: GraphWrapper::EdgeMap(_G, a), node_value(_G, a) { } marci@379: T operator[](const Edge& e) const { marci@379: switch (e.spec) { marci@379: case 0: marci@379: return (*this)[e]; marci@379: break; marci@379: case 1: marci@379: return node_value[e.n]; marci@379: break; marci@379: case 2: marci@379: return node_value[e.n]; marci@379: break; marci@379: } marci@379: } marci@379: void set(const Edge& e, T t) { marci@379: switch (e.spec) { marci@379: case 0: marci@379: GraphWrapper::set(e, t); marci@379: break; marci@379: case 1: marci@379: node_value.set(e, t); marci@379: break; marci@379: case 2: marci@379: node_value.set(e, t); marci@379: break; marci@379: } marci@379: } marci@379: }; marci@379: }; marci@379: marci@341: alpar@105: } //namespace hugo marci@76: marci@259: #endif //HUGO_GRAPH_WRAPPER_H marci@76: