src/work/marci/bipartite_graph_wrapper.h
author klao
Wed, 09 Mar 2005 14:23:36 +0000
changeset 1209 dc9fdf77007f
parent 986 e997802b855c
permissions -rw-r--r--
Fix a bug noticed by deba.
marci@174
     1
// -*- c++ -*-
alpar@921
     2
#ifndef LEMON_BIPARTITE_GRAPH_WRAPPER_H
alpar@921
     3
#define LEMON_BIPARTITE_GRAPH_WRAPPER_H
marci@76
     4
klao@491
     5
///\ingroup gwrappers
alpar@457
     6
///\file
alpar@457
     7
///\brief Several graph wrappers.
alpar@457
     8
///
alpar@457
     9
///This file contains several useful graph wrapper functions.
alpar@457
    10
///
alpar@457
    11
///\author Marton Makai
alpar@457
    12
alpar@921
    13
#include <lemon/invalid.h>
marci@368
    14
#include <iter_map.h>
alpar@921
    15
#include <lemon/graph_wrapper.h>
marci@762
    16
#include <for_each_macros.h>
marci@174
    17
alpar@921
    18
namespace lemon {
marci@76
    19
marci@641
    20
  /// \brief A wrapper for composing a bipartite graph from a graph 
marci@641
    21
  /// and from a node-map showing for any node which color class it belongs to.
marci@641
    22
  ///
marci@368
    23
  /// A wrapper for composing a bipartite graph.
marci@371
    24
  /// \c _graph have to be a reference to a graph of type \c Graph 
marci@371
    25
  /// and \c _s_false_t_true_map is an \c IterableBoolMap 
marci@368
    26
  /// reference containing the elements for the 
marci@371
    27
  /// color classes S and T. \c _graph is to be referred to an undirected 
marci@371
    28
  /// graph or a directed graph with edges oriented from S to T.
alpar@457
    29
  ///
marci@641
    30
  /// \author Marton Makai
marci@368
    31
  template<typename Graph> 
marci@368
    32
  class BipartiteGraphWrapper : public GraphWrapper<Graph> {
marci@768
    33
  public:
marci@389
    34
    typedef IterableBoolMap< typename Graph::template NodeMap<int> > 
marci@389
    35
    SFalseTTrueMap;
marci@768
    36
  protected:
marci@368
    37
    SFalseTTrueMap* s_false_t_true_map;
marci@393
    38
marci@501
    39
    BipartiteGraphWrapper() : GraphWrapper<Graph>()/*, 
marci@501
    40
						     S_CLASS(false), T_CLASS(true)*/ { }
marci@497
    41
    void setSFalseTTrueMap(SFalseTTrueMap& _s_false_t_true_map) { 
marci@499
    42
      s_false_t_true_map=&_s_false_t_true_map;
marci@497
    43
    }
marci@497
    44
marci@368
    45
  public:
marci@409
    46
    //marci
marci@409
    47
    //FIXME vhogy igy kellene, csak az en forditom nem eszi meg
marci@502
    48
    static const bool S_CLASS;
marci@502
    49
    static const bool T_CLASS;
marci@768
    50
marci@768
    51
    /// This method is to reach the iterable maps of the bipartite graph or 
marci@768
    52
    /// bipartite graph wrapper.
marci@768
    53
    const SFalseTTrueMap& sFalseTTrueMap() const { 
marci@768
    54
      return *s_false_t_true_map; 
marci@768
    55
    }
marci@379
    56
    
marci@501
    57
    //bool S_CLASS;
marci@501
    58
    //bool T_CLASS;
marci@409
    59
marci@368
    60
    BipartiteGraphWrapper(Graph& _graph, SFalseTTrueMap& _s_false_t_true_map) 
marci@500
    61
      : GraphWrapper<Graph>(_graph), 
marci@501
    62
	s_false_t_true_map(&_s_false_t_true_map)/*, 
marci@501
    63
						  S_CLASS(false), T_CLASS(true)*/ { }
marci@368
    64
    typedef typename GraphWrapper<Graph>::Node Node;
marci@368
    65
    //using GraphWrapper<Graph>::NodeIt;
marci@368
    66
    typedef typename GraphWrapper<Graph>::Edge Edge;
marci@368
    67
    //using GraphWrapper<Graph>::EdgeIt;
marci@393
    68
    class ClassNodeIt;
marci@393
    69
    friend class ClassNodeIt;
marci@393
    70
    class OutEdgeIt;
marci@393
    71
    friend class OutEdgeIt;
marci@393
    72
    class InEdgeIt;
marci@393
    73
    friend class InEdgeIt;
marci@902
    74
    class ClassNodeIt : public Node {
marci@393
    75
      friend class BipartiteGraphWrapper<Graph>;
marci@393
    76
    protected:
marci@902
    77
      const BipartiteGraphWrapper<Graph>* gw;
marci@368
    78
    public:
marci@379
    79
      ClassNodeIt() { }
marci@902
    80
      ClassNodeIt(Invalid i) : Node(i) { }
marci@902
    81
      ClassNodeIt(const BipartiteGraphWrapper<Graph>& _gw, bool _class) : 
marci@902
    82
	Node(), gw(&_gw) { 
marci@902
    83
	_gw.s_false_t_true_map->first(*this, _class); 
marci@368
    84
      }
marci@381
    85
      //FIXME needed in new concept, important here
marci@902
    86
      ClassNodeIt(const BipartiteGraphWrapper<Graph>& _gw, const Node& n) : 
marci@902
    87
	Node(n), gw(&_gw) { }
marci@902
    88
      ClassNodeIt& operator++() { 
marci@902
    89
	gw->s_false_t_true_map->next(*this);
marci@902
    90
	return *this; 
marci@902
    91
      }
marci@368
    92
    };
marci@379
    93
//     class SNodeIt {
marci@379
    94
//       Node n;
marci@379
    95
//     public:
marci@379
    96
//       SNodeIt() { }
marci@379
    97
//       SNodeIt(const Invalid& i) : n(i) { }
marci@379
    98
//       SNodeIt(const BipartiteGraphWrapper<Graph>& _G) { 
marci@379
    99
// 	_G.s_false_t_true_map->first(n, false); 
marci@379
   100
//       }
marci@379
   101
//       operator Node() const { return n; }
marci@379
   102
//     };
marci@379
   103
//     class TNodeIt {
marci@379
   104
//       Node n;
marci@379
   105
//     public:
marci@379
   106
//       TNodeIt() { }
marci@379
   107
//       TNodeIt(const Invalid& i) : n(i) { }
marci@379
   108
//       TNodeIt(const BipartiteGraphWrapper<Graph>& _G) { 
marci@379
   109
// 	_G.s_false_t_true_map->first(n, true); 
marci@379
   110
//       }
marci@379
   111
//       operator Node() const { return n; }
marci@379
   112
//     };
marci@902
   113
//     class OutEdgeIt { 
marci@902
   114
//       friend class BipartiteGraphWrapper<Graph>;
marci@902
   115
//     protected:
marci@902
   116
//       typename Graph::OutEdgeIt e;
marci@902
   117
//     public:
marci@902
   118
//       OutEdgeIt() { }
marci@902
   119
//       OutEdgeIt(const Invalid& i) : e(i) { }
marci@902
   120
//       OutEdgeIt(const BipartiteGraphWrapper<Graph>& _G, const Node& _n) {
marci@902
   121
// 	if (!(*(_G.s_false_t_true_map))[_n]) 
marci@902
   122
// 	  e=typename Graph::OutEdgeIt(*(_G.graph), typename Graph::Node(_n));
marci@902
   123
// 	else 
marci@902
   124
// 	  e=INVALID;
marci@902
   125
//       }
marci@902
   126
//       operator Edge() const { return Edge(typename Graph::Edge(e)); }
marci@902
   127
//     };
marci@902
   128
//     class InEdgeIt { 
marci@902
   129
//       friend class BipartiteGraphWrapper<Graph>;
marci@902
   130
//     protected:
marci@902
   131
//       typename Graph::InEdgeIt e;
marci@902
   132
//     public:
marci@902
   133
//       InEdgeIt() { }
marci@902
   134
//       InEdgeIt(const Invalid& i) : e(i) { }
marci@902
   135
//       InEdgeIt(const BipartiteGraphWrapper<Graph>& _G, const Node& _n) {
marci@902
   136
// 	if ((*(_G.s_false_t_true_map))[_n]) 
marci@902
   137
// 	  e=typename Graph::InEdgeIt(*(_G.graph), typename Graph::Node(_n));
marci@902
   138
// 	else 
marci@902
   139
// 	  e=INVALID;
marci@902
   140
//       }
marci@902
   141
//       operator Edge() const { return Edge(typename Graph::Edge(e)); }
marci@902
   142
//     };
marci@368
   143
marci@368
   144
    using GraphWrapper<Graph>::first;
marci@379
   145
    ClassNodeIt& first(ClassNodeIt& n, bool _class) const { 
marci@902
   146
      n=ClassNodeIt(*this, _class); return n;
marci@902
   147
    }
marci@379
   148
//    SNodeIt& first(SNodeIt& n) const { n=SNodeIt(*this); return n; }
marci@379
   149
//    TNodeIt& first(TNodeIt& n) const { n=TNodeIt(*this); return n; }
marci@902
   150
//     OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { 
marci@902
   151
//       i=OutEdgeIt(*this, p); return i;
marci@902
   152
//     }
marci@902
   153
//     InEdgeIt& first(InEdgeIt& i, const Node& p) const { 
marci@902
   154
//       i=InEdgeIt(*this, p); return i;
marci@902
   155
//     }
marci@368
   156
marci@902
   157
//     using GraphWrapper<Graph>::next;
marci@902
   158
//     ClassNodeIt& next(ClassNodeIt& n) const { 
marci@902
   159
//       this->s_false_t_true_map->next(n.n); return n; 
marci@902
   160
//     }
marci@379
   161
//     SNodeIt& next(SNodeIt& n) const { 
marci@379
   162
//       this->s_false_t_true_map->next(n); return n; 
marci@379
   163
//     }
marci@379
   164
//     TNodeIt& next(TNodeIt& n) const { 
marci@379
   165
//       this->s_false_t_true_map->next(n); return n; 
marci@379
   166
//     }
marci@902
   167
//     OutEdgeIt& next(OutEdgeIt& i) const { this->graph->next(i.e); return i; }
marci@902
   168
//     InEdgeIt& next(InEdgeIt& i) const { this->graph->next(i.e); return i; }
marci@368
   169
alpar@986
   170
//     Node source(const Edge& e) { 
alpar@986
   171
//       if (!(*(this->s_false_t_true_map))[this->graph->source(e)]) 
alpar@986
   172
// 	return Node(this->graph->source(e));
marci@902
   173
//       else
alpar@986
   174
// 	return Node(this->graph->target(e));	
marci@902
   175
//     }
alpar@986
   176
//     Node target(const Edge& e) { 
alpar@986
   177
//       if (!(*(this->s_false_t_true_map))[this->graph->source(e)]) 
alpar@986
   178
// 	return Node(this->graph->target(e));
marci@902
   179
//       else
alpar@986
   180
// 	return Node(this->graph->source(e));	
marci@902
   181
//     }
marci@368
   182
marci@902
   183
//     Node aNode(const OutEdgeIt& e) const { 
marci@902
   184
//       return Node(this->graph->aNode(e.e)); 
marci@902
   185
//     }
marci@902
   186
//     Node aNode(const InEdgeIt& e) const { 
marci@902
   187
//       return Node(this->graph->aNode(e.e)); 
marci@902
   188
//     }
marci@902
   189
//     Node bNode(const OutEdgeIt& e) const { 
marci@902
   190
//       return Node(this->graph->bNode(e.e)); 
marci@902
   191
//     }
marci@902
   192
//     Node bNode(const InEdgeIt& e) const { 
marci@902
   193
//       return Node(this->graph->bNode(e.e)); 
marci@902
   194
//     }
marci@379
   195
marci@641
   196
    /// Returns true iff \c n is in S.
marci@379
   197
    bool inSClass(const Node& n) const {
marci@381
   198
      return !(*(this->s_false_t_true_map))[n];
marci@379
   199
    }
marci@641
   200
marci@641
   201
    /// Returns true iff \c n is in T.
marci@379
   202
    bool inTClass(const Node& n) const {
marci@381
   203
      return (*(this->s_false_t_true_map))[n];
marci@379
   204
    }
marci@368
   205
  };
marci@368
   206
marci@502
   207
marci@502
   208
  template<typename G>
marci@502
   209
  const bool BipartiteGraphWrapper<G>::S_CLASS=false;
marci@502
   210
  template<typename G>
marci@502
   211
  const bool BipartiteGraphWrapper<G>::T_CLASS=true;
marci@502
   212
marci@641
   213
  /// \brief A bipartite graph template class
marci@641
   214
  ///
marci@641
   215
  /// This class composes a bipartite graph over a directed or undirected 
marci@641
   216
  /// graph structure of type \c Graph.
marci@641
   217
  /// \c _graph have to be a reference to a graph of type \c Graph 
marci@641
   218
  /// and \c _s_false_t_true_map is an \c IterableBoolMap 
marci@641
   219
  /// reference containing the elements for the 
marci@641
   220
  /// color classes S and T. \c _graph is to be referred to an undirected 
marci@641
   221
  /// graph or a directed graph with edges oriented from S to T.
marci@641
   222
  ///
marci@641
   223
  ///\bug experimental. Do not use this while the bipartitemap augmentation 
marci@497
   224
  /// does not work well.
marci@497
   225
  template<typename Graph>
marci@497
   226
  class BipartiteGraph : public BipartiteGraphWrapper<Graph> {
marci@768
   227
//     typedef IterableBoolMap< typename Graph::template NodeMap<int> > 
marci@768
   228
//     SFalseTTrueMap;
marci@497
   229
    typedef BipartiteGraphWrapper<Graph> Parent;
marci@497
   230
  protected:
marci@497
   231
    Graph gr;
marci@497
   232
    typename Graph::template NodeMap<int> bipartite_map;
marci@768
   233
    typename Parent::SFalseTTrueMap s_false_t_true_map;
marci@497
   234
  public:
marci@497
   235
    typedef typename Parent::Node Node;
marci@497
   236
    typedef typename Parent::Edge Edge;
marci@499
   237
    BipartiteGraph() : BipartiteGraphWrapper<Graph>(), 
marci@500
   238
		       gr(), bipartite_map(gr, -1), 
marci@497
   239
		       s_false_t_true_map(bipartite_map) { 
marci@497
   240
      Parent::setGraph(gr); 
marci@499
   241
      Parent::setSFalseTTrueMap(s_false_t_true_map);
marci@497
   242
    }
marci@497
   243
marci@497
   244
    /// the \c bool parameter which can be \c S_Class or \c T_Class shows 
marci@497
   245
    /// the color class where the new node is to be inserted.
marci@498
   246
    Node addNode(bool b) {
marci@498
   247
      Node n=Parent::graph->addNode();
marci@498
   248
      bipartite_map.update();
marci@501
   249
      //bipartite_map.set(n, -1);
marci@498
   250
      s_false_t_true_map.insert(n, b);
marci@498
   251
      return n;
marci@498
   252
    }
marci@497
   253
marci@497
   254
    /// A new edge is inserted.
alpar@986
   255
    ///\pre \c source have to be in \c S_Class and \c target in \c T_Class.
alpar@986
   256
    Edge addEdge(const Node& source, const Node& target) {
alpar@986
   257
      return Parent::graph->addEdge(source, target);
marci@498
   258
    }
marci@497
   259
marci@498
   260
    void erase(const Node& n) {
marci@498
   261
      s_false_t_true_map.remove(n);
marci@498
   262
      Parent::graph->erase(n);
marci@498
   263
    }
marci@498
   264
    void erase(const Edge& e) {
marci@498
   265
      Parent::graph->erase(e);
marci@498
   266
    }
marci@497
   267
    
marci@497
   268
    void clear() {
marci@558
   269
      FOR_EACH_LOC(typename Parent::EdgeIt, e, *this) erase(e);
marci@558
   270
      FOR_EACH_LOC(typename Parent::NodeIt, n, *this) erase(n);
marci@497
   271
    }
marci@497
   272
  };
marci@497
   273
marci@768
   274
  template<typename Graph, typename sIterableMap, typename tIterableMap>
marci@768
   275
  class stGraphWrapper;
marci@497
   276
marci@768
   277
  /// Easier stuff for bipartite graphs.
marci@435
   278
  template<typename Graph>
marci@768
   279
  class stBipartiteGraphWrapper : public 
marci@768
   280
  stGraphWrapper<Graph, typename Graph::SFalseTTrueMap, 
marci@768
   281
		 typename Graph::SFalseTTrueMap> {
marci@768
   282
  public:
marci@768
   283
    typedef stGraphWrapper<Graph, typename Graph::SFalseTTrueMap, 
marci@768
   284
			   typename Graph::SFalseTTrueMap> Parent;
marci@768
   285
    stBipartiteGraphWrapper(Graph& _graph) : 
marci@768
   286
      Parent(_graph, _graph.sFalseTTrueMap(), _graph.sFalseTTrueMap()) { }
marci@768
   287
  };
marci@435
   288
marci@435
   289
//   template<typename Graph> 
marci@435
   290
//   std::ostream& 
marci@435
   291
//   operator<<(std::ostream& os, const typename stGraphWrapper<Graph>::Node& i) { 
marci@435
   292
//     os << "(node: " << typename Graph::Node(i) << " spec: " << i.spec <<")"; 
marci@435
   293
//     return os; 
marci@435
   294
//   }
marci@435
   295
//   template<typename Graph> 
marci@435
   296
//   std::ostream& 
marci@435
   297
//   operator<<(std::ostream& os, const typename stGraphWrapper<Graph>::Edge& i) { 
marci@435
   298
//     os << "(edge: " << typename Graph::Edge(i) << " spec: " << i.spec << 
marci@435
   299
//       " node: " << i.n << ")"; 
marci@435
   300
//     return os; 
marci@435
   301
//   }
marci@341
   302
marci@641
   303
  /// \brief A wrapper for adding extra nodes s and t to a bipartite graph
marci@641
   304
  /// and edges from s to each node of S and form each node of T to t.
marci@641
   305
  /// 
marci@641
   306
  /// A wrapper for adding extra nodes s and t to a bipartite graph
marci@641
   307
  /// and edges from s to each node of S and form each node of T to t.
marci@641
   308
  /// This class is very useful to reduce some matching or more
marci@641
   309
  /// generally, capacitataed b-matching problem to a flow problem.
marci@641
   310
  /// According to the bipartite graph concepts the bipartite 
marci@641
   311
  /// graph have to be oriented from S to T.
alpar@457
   312
  ///
marci@641
   313
  /// \author Marton Makai
marci@768
   314
  template<typename Graph, typename sIterableMap, typename tIterableMap>
marci@379
   315
  class stGraphWrapper : public GraphWrapper<Graph> {
marci@768
   316
  protected:    
marci@768
   317
    const sIterableMap* s_iterable_map;
marci@768
   318
    const tIterableMap* t_iterable_map;
marci@379
   319
  public:
marci@379
   320
    class Node; 
marci@381
   321
    friend class Node;
marci@379
   322
//GN, int
marci@768
   323
//0 normalis, 1 s, 2 t, ez az iteralasi sorrend, 
marci@379
   324
//es a vege a false azaz (invalid, 3)    
marci@379
   325
    class NodeIt;
marci@381
   326
    friend class NodeIt;
marci@379
   327
//GNI, int
marci@379
   328
    class Edge;
marci@381
   329
    friend class Edge;
marci@379
   330
//GE, int, GN
marci@379
   331
//0 normalis, 1 s->vmi, 2 vmi->t, ez a sorrend,
marci@379
   332
//invalid: (invalid, 3, invalid)
marci@379
   333
    class OutEdgeIt;
marci@381
   334
    friend class OutEdgeIt;
marci@379
   335
//GO, int, GNI
marci@379
   336
//normalis pontbol (first, 0, invalid), ..., (invalid, 2, vmi), ... (invalid, 3, invalid)
marci@379
   337
//s-bol (invalid, 1, first), ... (invalid, 3, invalid)
marci@379
   338
//t-bol (invalid, 3, invalid)
marci@379
   339
    class InEdgeIt;
marci@381
   340
    friend class InEdgeIt;
marci@379
   341
//GI, int, GNI
marci@379
   342
//normalis pontbol (first, 0, invalid), ..., (invalid, 1, vmi), ... (invalid, 3, invalid)
marci@379
   343
//s-be (invalid, 3, invalid)
marci@379
   344
//t-be (invalid, 2, first), ... (invalid, 3, invalid)
marci@379
   345
    class EdgeIt;
marci@381
   346
    friend class EdgeIt;
marci@379
   347
//(first, 0, invalid) ...
marci@379
   348
//(invalid, 1, vmi)
marci@379
   349
//(invalid, 2, vmi)
marci@379
   350
//invalid, 3, invalid)
marci@379
   351
    template <typename T> class NodeMap;
marci@510
   352
    template <typename T> class EdgeMap;
marci@341
   353
marci@379
   354
//    template <typename T> friend class NodeMap;
marci@379
   355
//    template <typename T> friend class EdgeMap;
marci@341
   356
marci@502
   357
    ///\todo FIXME ezt majd static-ra kell javitani
marci@379
   358
    const Node S_NODE;
marci@379
   359
    const Node T_NODE;
marci@341
   360
marci@379
   361
    static const bool S_CLASS=false;
marci@379
   362
    static const bool T_CLASS=true;
marci@341
   363
marci@768
   364
    // \bug not too nice constructor.
marci@768
   365
    stGraphWrapper(Graph& _graph, 
marci@768
   366
		   const sIterableMap& _s_iterable_map, 
marci@768
   367
		   const tIterableMap& _t_iterable_map) : 
marci@768
   368
      GraphWrapper<Graph>(_graph), 
marci@768
   369
      s_iterable_map(&_s_iterable_map), 
marci@768
   370
      t_iterable_map(&_t_iterable_map), 
marci@768
   371
      S_NODE(INVALID, 1), 
marci@768
   372
      T_NODE(INVALID, 2) { }
marci@341
   373
marci@435
   374
    
marci@435
   375
//    std::ostream& 
marci@435
   376
//    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Node& i);
marci@435
   377
//    friend std::ostream& 
marci@435
   378
//    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Node& i);
marci@435
   379
//    friend std::ostream& 
marci@435
   380
//    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Edge& i);
marci@435
   381
marci@379
   382
    class Node : public Graph::Node {
marci@379
   383
    protected:
marci@379
   384
      friend class GraphWrapper<Graph>;
marci@768
   385
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@389
   386
      template <typename T> friend class NodeMap;
marci@380
   387
      friend class Edge;
marci@380
   388
      friend class OutEdgeIt;
marci@380
   389
      friend class InEdgeIt;
marci@380
   390
      friend class EdgeIt;
marci@379
   391
      int spec; 
marci@379
   392
    public:
marci@379
   393
      Node() { }
marci@379
   394
      Node(const typename Graph::Node& _n, int _spec=0) : 
marci@379
   395
	Graph::Node(_n), spec(_spec) { }
marci@379
   396
      Node(const Invalid& i) : Graph::Node(i), spec(3) { }
marci@379
   397
      friend bool operator==(const Node& u, const Node& v) { 
marci@379
   398
	return (u.spec==v.spec && 
marci@379
   399
		static_cast<typename Graph::Node>(u)==
marci@379
   400
		static_cast<typename Graph::Node>(v));
marci@379
   401
      } 
marci@379
   402
      friend bool operator!=(const Node& u, const Node& v) { 
marci@379
   403
	return (v.spec!=u.spec || 
marci@379
   404
		static_cast<typename Graph::Node>(u)!=
marci@379
   405
		static_cast<typename Graph::Node>(v));
marci@409
   406
      }
marci@435
   407
//      template<typename G> 
marci@435
   408
//      friend std::ostream& 
marci@435
   409
//      operator<<(std::ostream& os, const typename stGraphWrapper<G>::Node& i); 
marci@435
   410
      friend std::ostream& operator<< (std::ostream& os, const Node& i);
marci@379
   411
      int getSpec() const { return spec; }
marci@379
   412
    };
marci@409
   413
marci@379
   414
    class NodeIt { 
marci@379
   415
      friend class GraphWrapper<Graph>;
marci@768
   416
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   417
      typename Graph::NodeIt n;
marci@379
   418
      int spec; 
marci@379
   419
     public:
marci@379
   420
      NodeIt() { }
marci@379
   421
      NodeIt(const typename Graph::NodeIt& _n, int _spec) : 
marci@379
   422
	n(_n), spec(_spec) { }
marci@379
   423
      NodeIt(const Invalid& i) : n(i), spec(3) { }
marci@768
   424
      NodeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) 
marci@768
   425
	: n(*(_G.graph)), spec(0) { 
marci@409
   426
	if (!_G.graph->valid(n)) spec=1;
marci@379
   427
      }
marci@379
   428
      operator Node() const { return Node(n, spec); }
marci@379
   429
    };
marci@409
   430
marci@379
   431
    class Edge : public Graph::Edge {
marci@379
   432
      friend class GraphWrapper<Graph>;
marci@768
   433
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@510
   434
      template <typename T> friend class EdgeMap;
marci@379
   435
      int spec;
marci@379
   436
      typename Graph::Node n;
marci@379
   437
    public:
marci@379
   438
      Edge() { }
marci@379
   439
      Edge(const typename Graph::Edge& _e, int _spec, 
marci@379
   440
	   const typename Graph::Node& _n) : 
marci@379
   441
	Graph::Edge(_e), spec(_spec), n(_n) { 
marci@379
   442
      }
marci@379
   443
      Edge(const Invalid& i) : Graph::Edge(i), spec(3), n(i) { }
marci@379
   444
      friend bool operator==(const Edge& u, const Edge& v) { 
marci@379
   445
	return (u.spec==v.spec && 
marci@379
   446
		static_cast<typename Graph::Edge>(u)==
marci@379
   447
		static_cast<typename Graph::Edge>(v) && 
marci@379
   448
		u.n==v.n);
marci@379
   449
      } 
marci@379
   450
      friend bool operator!=(const Edge& u, const Edge& v) { 
marci@379
   451
	return (v.spec!=u.spec || 
marci@379
   452
		static_cast<typename Graph::Edge>(u)!=
marci@379
   453
		static_cast<typename Graph::Edge>(v) || 
marci@379
   454
		u.n!=v.n);
marci@379
   455
      } 
marci@435
   456
//      template<typename G> 
marci@435
   457
//      friend std::ostream& 
marci@435
   458
//      operator<<(std::ostream& os, const typename stGraphWrapper<G>::Edge& i); 
marci@435
   459
      friend std::ostream& operator<< (std::ostream& os, const Edge& i);
marci@379
   460
      int getSpec() const { return spec; }
marci@510
   461
      typename Graph::Node getNode() const { return n; }
marci@379
   462
    };
marci@409
   463
marci@379
   464
    class OutEdgeIt { 
marci@379
   465
      friend class GraphWrapper<Graph>;
marci@768
   466
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   467
      typename Graph::OutEdgeIt e;
marci@379
   468
      int spec;
marci@379
   469
      typename Graph::ClassNodeIt n;
marci@379
   470
    public:
marci@379
   471
      OutEdgeIt() { }
marci@379
   472
      OutEdgeIt(const typename Graph::OutEdgeIt& _e, int _spec, 
marci@379
   473
		const typename Graph::ClassNodeIt& _n) : 
marci@379
   474
	e(_e), spec(_spec), n(_n) { 
marci@379
   475
      }
marci@379
   476
      OutEdgeIt(const Invalid& i) : e(i), spec(3), n(i) { }
marci@768
   477
      OutEdgeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, 
marci@768
   478
		const Node& _n) {
marci@379
   479
	switch (_n.spec) {
marci@379
   480
	  case 0 : 
marci@381
   481
	    if (_G.graph->inSClass(_n)) { //S, van normalis kiel 
marci@379
   482
	      e=typename Graph::OutEdgeIt(*(_G.graph), 
marci@379
   483
					  typename Graph::Node(_n)); 
marci@379
   484
	      spec=0;
marci@379
   485
	      n=INVALID;
marci@379
   486
	      if (!_G.graph->valid(e)) spec=3;
marci@379
   487
	    } else { //T, specko kiel van
marci@379
   488
	      e=INVALID;
marci@379
   489
	      spec=2;
marci@379
   490
	      n=_n;
marci@379
   491
	    }
marci@379
   492
	    break;
marci@379
   493
	  case 1:
marci@379
   494
	    e=INVALID;
marci@379
   495
	    spec=1;
marci@379
   496
	    _G.graph->first(n, S_CLASS); //s->vmi;
marci@379
   497
	    if (!_G.graph->valid(n)) spec=3; //Ha S ures
marci@379
   498
	    break;
marci@379
   499
	  case 2:
marci@379
   500
	    e=INVALID;
marci@379
   501
	    spec=3;
marci@379
   502
	    n=INVALID;
marci@379
   503
	    break;
marci@379
   504
	}
marci@379
   505
      }
marci@379
   506
      operator Edge() const { return Edge(e, spec, n); }
marci@379
   507
    };
marci@409
   508
marci@379
   509
    class InEdgeIt { 
marci@379
   510
      friend class GraphWrapper<Graph>;
marci@768
   511
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   512
      typename Graph::InEdgeIt e;
marci@379
   513
      int spec;
marci@379
   514
      typename Graph::ClassNodeIt n;
marci@379
   515
    public:
marci@379
   516
      InEdgeIt() { }
marci@379
   517
      InEdgeIt(const typename Graph::InEdgeIt& _e, int _spec, 
marci@379
   518
	       const typename Graph::ClassNodeIt& _n) : 
marci@379
   519
	e(_e), spec(_spec), n(_n) { 
marci@379
   520
      }
marci@379
   521
      InEdgeIt(const Invalid& i) : e(i), spec(3), n(i) { }
marci@768
   522
      InEdgeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, 
marci@768
   523
	       const Node& _n) {
marci@379
   524
	switch (_n.spec) {
marci@379
   525
	  case 0 : 
marci@381
   526
	    if (_G.graph->inTClass(_n)) { //T, van normalis beel 
marci@379
   527
	      e=typename Graph::InEdgeIt(*(_G.graph), 
marci@379
   528
					 typename Graph::Node(_n)); 
marci@379
   529
	      spec=0;
marci@379
   530
	      n=INVALID;
marci@379
   531
	      if (!_G.graph->valid(e)) spec=3;
marci@379
   532
	    } else { //S, specko beel van
marci@379
   533
	      e=INVALID;
marci@379
   534
	      spec=1;
marci@379
   535
	      n=_n;
marci@379
   536
	    }
marci@379
   537
	    break;
marci@379
   538
	  case 1:
marci@379
   539
	    e=INVALID;
marci@379
   540
	    spec=3;
marci@379
   541
	    n=INVALID;
marci@409
   542
	    break;
marci@379
   543
	  case 2:
marci@379
   544
	    e=INVALID;
marci@409
   545
	    spec=2;
marci@379
   546
	    _G.graph->first(n, T_CLASS); //vmi->t;
marci@379
   547
	    if (!_G.graph->valid(n)) spec=3; //Ha T ures
marci@379
   548
	    break;
marci@379
   549
	}
marci@379
   550
      }
marci@379
   551
      operator Edge() const { return Edge(e, spec, n); }
marci@379
   552
    };
marci@409
   553
marci@379
   554
    class EdgeIt { 
marci@379
   555
      friend class GraphWrapper<Graph>;
marci@768
   556
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   557
      typename Graph::EdgeIt e;
marci@379
   558
      int spec;
marci@379
   559
      typename Graph::ClassNodeIt n;
marci@379
   560
    public:
marci@379
   561
      EdgeIt() { }
marci@379
   562
      EdgeIt(const typename Graph::EdgeIt& _e, int _spec, 
marci@379
   563
	     const typename Graph::ClassNodeIt& _n) : 
marci@379
   564
	e(_e), spec(_spec), n(_n) { }
marci@379
   565
      EdgeIt(const Invalid& i) : e(i), spec(3), n(i) { }
marci@768
   566
      EdgeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) : 
marci@379
   567
	e(*(_G.graph)), spec(0), n(INVALID) { 
marci@379
   568
	if (!_G.graph->valid(e)) {
marci@379
   569
	  spec=1;
marci@379
   570
	  _G.graph->first(n, S_CLASS);
marci@379
   571
	  if (!_G.graph->valid(n)) { //Ha S ures
marci@379
   572
	    spec=2;
marci@379
   573
	    _G.graph->first(n, T_CLASS);
marci@379
   574
	    if (!_G.graph->valid(n)) { //Ha T ures
marci@379
   575
	      spec=3;
marci@379
   576
	    }
marci@379
   577
	  }
marci@379
   578
	}
marci@379
   579
      }
marci@379
   580
      operator Edge() const { return Edge(e, spec, n); }
marci@379
   581
    };
marci@341
   582
   
marci@379
   583
    NodeIt& first(NodeIt& i) const { 
marci@379
   584
      i=NodeIt(*this); return i;
marci@379
   585
    }
marci@379
   586
    OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { 
marci@379
   587
      i=OutEdgeIt(*this, p); return i;
marci@379
   588
    }
marci@379
   589
    InEdgeIt& first(InEdgeIt& i, const Node& p) const { 
marci@379
   590
      i=InEdgeIt(*this, p); return i;
marci@379
   591
    }
marci@379
   592
    EdgeIt& first(EdgeIt& i) const { 
marci@379
   593
      i=EdgeIt(*this); return i;
marci@379
   594
    }
marci@341
   595
marci@379
   596
    NodeIt& next(NodeIt& i) const { 
marci@379
   597
      switch (i.spec) {
marci@379
   598
	case 0:
marci@389
   599
	  this->graph->next(i.n);
marci@389
   600
	  if (!this->graph->valid(i.n)) {
marci@379
   601
	    i.spec=1;
marci@379
   602
	  }
marci@379
   603
	  break;
marci@379
   604
	case 1:
marci@379
   605
	  i.spec=2;
marci@379
   606
	  break;
marci@379
   607
	case 2:
marci@379
   608
	  i.spec=3;
marci@379
   609
	  break;
marci@379
   610
      }
marci@379
   611
      return i; 
marci@379
   612
    }
marci@379
   613
    OutEdgeIt& next(OutEdgeIt& i) const { 
marci@393
   614
      typename Graph::Node v;
marci@379
   615
      switch (i.spec) {
marci@379
   616
	case 0: //normal edge
marci@409
   617
	  v=this->graph->aNode(i.e);
marci@389
   618
	  this->graph->next(i.e);
marci@389
   619
	  if (!this->graph->valid(i.e)) { //Az igazi elek vegere ertunk
marci@389
   620
	    if (this->graph->inSClass(v)) { //S, nincs kiel
marci@379
   621
	      i.spec=3;
marci@379
   622
	      i.n=INVALID;
marci@379
   623
	    } else { //T, van kiel
marci@379
   624
	      i.spec=2; 
marci@379
   625
	      i.n=v;
marci@379
   626
	    }
marci@379
   627
	  }
marci@379
   628
	  break;
marci@379
   629
	case 1: //s->vmi
marci@389
   630
	  this->graph->next(i.n);
marci@389
   631
	  if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   632
	  break;
marci@379
   633
	case 2: //vmi->t
marci@379
   634
	  i.spec=3;
marci@379
   635
	  i.n=INVALID;
marci@379
   636
	  break;
marci@379
   637
      }
marci@379
   638
      return i; 
marci@379
   639
    }
marci@379
   640
    InEdgeIt& next(InEdgeIt& i) const { 
marci@393
   641
      typename Graph::Node v;
marci@379
   642
      switch (i.spec) {
marci@379
   643
	case 0: //normal edge
marci@393
   644
	  v=this->graph->aNode(i.e);
marci@389
   645
	  this->graph->next(i.e);
marci@389
   646
	  if (!this->graph->valid(i.e)) { //Az igazi elek vegere ertunk
marci@389
   647
	    if (this->graph->inTClass(v)) { //S, nincs beel
marci@379
   648
	      i.spec=3;
marci@379
   649
	      i.n=INVALID;
marci@379
   650
	    } else { //S, van beel
marci@379
   651
	      i.spec=1; 
marci@379
   652
	      i.n=v;
marci@379
   653
	    }
marci@379
   654
	  }
marci@379
   655
	  break;
marci@379
   656
	case 1: //s->vmi
marci@379
   657
	  i.spec=3;
marci@379
   658
	  i.n=INVALID;
marci@379
   659
	  break;
marci@379
   660
	case 2: //vmi->t
marci@389
   661
	  this->graph->next(i.n);
marci@389
   662
	  if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   663
	  break;
marci@379
   664
      }
marci@379
   665
      return i; 
marci@379
   666
    }
marci@341
   667
marci@379
   668
    EdgeIt& next(EdgeIt& i) const { 
marci@379
   669
      switch (i.spec) {
marci@379
   670
	case 0:
marci@389
   671
	  this->graph->next(i.e);
marci@389
   672
	  if (!this->graph->valid(i.e)) { 
marci@379
   673
	    i.spec=1;
marci@389
   674
	    this->graph->first(i.n, S_CLASS);
marci@389
   675
	    if (!this->graph->valid(i.n)) {
marci@379
   676
	      i.spec=2;
marci@389
   677
	      this->graph->first(i.n, T_CLASS);
marci@389
   678
	      if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   679
	    }
marci@379
   680
	  }
marci@379
   681
	  break;
marci@379
   682
	case 1:
marci@389
   683
	  this->graph->next(i.n);
marci@389
   684
	  if (!this->graph->valid(i.n)) {
marci@379
   685
	    i.spec=2;
marci@389
   686
	    this->graph->first(i.n, T_CLASS);
marci@389
   687
	    if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   688
	  }
marci@379
   689
	  break;
marci@379
   690
	case 2:
marci@389
   691
	  this->graph->next(i.n);
marci@389
   692
	  if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   693
	  break;
marci@379
   694
      }
marci@379
   695
      return i; 
marci@379
   696
    }    
marci@341
   697
alpar@986
   698
    Node source(const Edge& e) const { 
marci@379
   699
      switch (e.spec) {
marci@393
   700
      case 0: 
alpar@986
   701
	return Node(this->graph->source(e));
marci@393
   702
	break;
marci@393
   703
      case 1:
marci@393
   704
	return S_NODE;
marci@393
   705
	break;
marci@393
   706
      case 2:
marci@393
   707
      default:
marci@393
   708
	return Node(e.n);
marci@393
   709
	break;
marci@379
   710
      }
marci@379
   711
    }
alpar@986
   712
    Node target(const Edge& e) const { 
marci@379
   713
      switch (e.spec) {
marci@393
   714
      case 0: 
alpar@986
   715
	return Node(this->graph->target(e));
marci@393
   716
	break;
marci@393
   717
      case 1:
marci@393
   718
	return Node(e.n);
marci@393
   719
	break;
marci@393
   720
      case 2:
marci@393
   721
      default:
marci@393
   722
	return T_NODE;
marci@393
   723
	break;
marci@379
   724
      }
marci@379
   725
    }
marci@341
   726
marci@379
   727
    bool valid(const Node& n) const { return (n.spec<3); }
marci@379
   728
    bool valid(const Edge& e) const { return (e.spec<3); }
marci@379
   729
marci@409
   730
    int nodeNum() const { return this->graph->nodeNum()+2; }
marci@409
   731
    int edgeNum() const { 
marci@409
   732
      return this->graph->edgeNum()+this->graph->nodeNum(); 
marci@409
   733
    }
marci@341
   734
  
alpar@986
   735
    Node aNode(const OutEdgeIt& e) const { return source(e); }
alpar@986
   736
    Node aNode(const InEdgeIt& e) const { return target(e); }
alpar@986
   737
    Node bNode(const OutEdgeIt& e) const { return target(e); }
alpar@986
   738
    Node bNode(const InEdgeIt& e) const { return source(e); }
marci@409
   739
marci@409
   740
    void addNode() const { }
marci@409
   741
    void addEdge() const { }
marci@409
   742
    
marci@389
   743
//    Node addNode() const { return Node(this->graph->addNode()); }
alpar@986
   744
//    Edge addEdge(const Node& source, const Node& target) const { 
alpar@986
   745
//      return Edge(this->graph->addEdge(source, target)); }
marci@341
   746
marci@389
   747
//    void erase(const Node& i) const { this->graph->erase(i); }
marci@389
   748
//    void erase(const Edge& i) const { this->graph->erase(i); }
marci@341
   749
  
marci@389
   750
//    void clear() const { this->graph->clear(); }
marci@341
   751
    
marci@389
   752
    template<typename T> class NodeMap : public GraphWrapper<Graph>::template NodeMap<T> { 
marci@389
   753
      typedef typename GraphWrapper<Graph>::template NodeMap<T> Parent;
marci@510
   754
    protected:
marci@379
   755
      T s_value, t_value;
marci@379
   756
    public:
marci@768
   757
      NodeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) : 
marci@768
   758
	Parent(_G), 
marci@768
   759
	s_value(), 
marci@768
   760
	t_value() { }
marci@768
   761
      NodeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, T a) 
marci@768
   762
	: Parent(_G, a), 
marci@768
   763
	  s_value(a), 
marci@768
   764
	  t_value(a) { }
marci@379
   765
      T operator[](const Node& n) const { 
marci@379
   766
	switch (n.spec) {
marci@393
   767
	case 0: 
marci@393
   768
	  return Parent::operator[](n);
marci@393
   769
	case 1:
marci@393
   770
	  return s_value;
marci@393
   771
	case 2: 
marci@393
   772
	default:
marci@393
   773
	  return t_value;
marci@379
   774
	}
marci@379
   775
      }
marci@379
   776
      void set(const Node& n, T t) { 
marci@379
   777
	switch (n.spec) {
marci@393
   778
	case 0: 
marci@393
   779
	  GraphWrapper<Graph>::template NodeMap<T>::set(n, t);
marci@393
   780
	  break;
marci@393
   781
	case 1:
marci@393
   782
	  s_value=t;
marci@393
   783
	  break;
marci@393
   784
	case 2:
marci@393
   785
	default:
marci@393
   786
	  t_value=t;
marci@393
   787
	  break;
marci@379
   788
	}
marci@379
   789
      }
marci@379
   790
    };
marci@341
   791
marci@510
   792
    /// This class is to wrap a node-map of \c Graph and two variables 
marci@510
   793
    /// storing values for \c S_NODE and \c T_NODE to a node-map of 
marci@768
   794
    /// stGraphWrapper<Graph, sIterableMap, tIterableMap>.
marci@510
   795
    template<typename NM> class NodeMapWrapper { 
marci@510
   796
    public:
alpar@987
   797
      typedef Node Key;
alpar@987
   798
      typedef typename NM::Value Value;
marci@510
   799
    protected:
marci@510
   800
      NM* nm;
alpar@987
   801
      Value* s_value, t_value;
marci@510
   802
    public:
alpar@987
   803
      NodeMapWrapper(NM& _nm, Value& _s_value, Value& _t_value) : 
marci@510
   804
	nm(&_nm), s_value(&_s_value), t_value(&_t_value) { }
alpar@987
   805
      Value operator[](const Node& n) const { 
marci@510
   806
	switch (n.getSpec()) {
marci@510
   807
	case 0: 
marci@510
   808
	  return (*nm)[n];
marci@510
   809
	case 1:
marci@510
   810
	  return *s_value;
marci@510
   811
	case 2: 
marci@510
   812
	default:
marci@510
   813
	  return *t_value;
marci@510
   814
	}
marci@510
   815
      }
alpar@987
   816
      void set(const Node& n, Value t) { 
marci@510
   817
	switch (n.getSpec()) {
marci@510
   818
	case 0: 
marci@510
   819
	  nm->set(n, t);
marci@510
   820
	  break;
marci@510
   821
	case 1:
marci@510
   822
	  *s_value=t;
marci@510
   823
	  break;
marci@510
   824
	case 2:
marci@510
   825
	default:
marci@510
   826
	  *t_value=t;
marci@510
   827
	  break;
marci@510
   828
	}
marci@510
   829
      }
marci@510
   830
    };
marci@510
   831
marci@510
   832
    template<typename T> 
marci@510
   833
    class EdgeMap : public GraphWrapper<Graph>::template EdgeMap<T> { 
marci@510
   834
      typedef typename GraphWrapper<Graph>::template EdgeMap<T> Parent;
marci@510
   835
    protected:
marci@389
   836
      typename GraphWrapper<Graph>::template NodeMap<T> node_value;
marci@379
   837
    public:
marci@768
   838
      EdgeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) 
marci@768
   839
	: Parent(_G), 
marci@768
   840
	  node_value(_G) { }
marci@768
   841
      EdgeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, T a) 
marci@768
   842
	: Parent(_G, a), 
marci@768
   843
	  node_value(_G, a) { }
marci@379
   844
      T operator[](const Edge& e) const { 
marci@379
   845
	switch (e.spec) {
marci@393
   846
	case 0: 
marci@393
   847
	  return Parent::operator[](e);
marci@393
   848
	case 1:
marci@393
   849
	  return node_value[e.n];
marci@393
   850
	case 2:
marci@393
   851
	default:
marci@393
   852
	  return node_value[e.n];
marci@379
   853
	}
marci@379
   854
      }
marci@379
   855
      void set(const Edge& e, T t) { 
marci@379
   856
	switch (e.spec) {
marci@393
   857
	case 0: 
marci@409
   858
	  Parent::set(e, t);
marci@393
   859
	  break;
marci@393
   860
	case 1:
marci@393
   861
	  node_value.set(e.n, t);
marci@393
   862
	  break;
marci@393
   863
	case 2:
marci@393
   864
	default:
marci@393
   865
	  node_value.set(e.n, t);
marci@393
   866
	  break;
marci@379
   867
	}
marci@379
   868
      }
marci@379
   869
    };
marci@409
   870
marci@510
   871
    /// This class is to wrap an edge-map and a node-map of \c Graph 
marci@768
   872
    /// to an edge-map of stGraphWrapper<Graph, sIterableMap, tIterableMap>.
marci@510
   873
    template<typename EM, typename NM> 
marci@510
   874
    class EdgeMapWrapper {
marci@510
   875
    public: 
alpar@987
   876
      typedef Edge Key;
alpar@987
   877
      typedef typename EM::Value Value;
marci@510
   878
    protected:
marci@510
   879
      EM* em;
marci@510
   880
      NM* nm;
marci@510
   881
    public:
marci@510
   882
      EdgeMapWrapper(EM& _em, NM& _nm) : em(&_em), nm(&_nm) { }
alpar@987
   883
      Value operator[](const Edge& e) const { 
marci@510
   884
	switch (e.getSpec()) {
marci@510
   885
	case 0: 
marci@510
   886
	  return (*em)[e];
marci@510
   887
	case 1:
marci@510
   888
	  return (*nm)[e.getNode()];
marci@510
   889
	case 2:
marci@510
   890
	default:
marci@510
   891
	  return (*nm)[e.getNode()];
marci@510
   892
	}
marci@510
   893
      }
alpar@987
   894
      void set(const Edge& e, Value t) { 
marci@510
   895
	switch (e.getSpec()) {
marci@510
   896
	case 0: 
marci@510
   897
	  em->set(e, t);
marci@510
   898
	  break;
marci@510
   899
	case 1:
marci@510
   900
	  nm->set(e.getNode(), t);
marci@510
   901
	  break;
marci@510
   902
	case 2:
marci@510
   903
	default:
marci@510
   904
	  nm->set(e.getNode(), t);
marci@510
   905
	  break;
marci@510
   906
	}
marci@510
   907
      }
marci@510
   908
    };
marci@510
   909
marci@409
   910
marci@435
   911
//  template<typename G> 
marci@435
   912
    friend std::ostream& 
marci@435
   913
    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Node& i) { 
marci@409
   914
      os << "(node: " << typename Graph::Node(i) << " spec: " << i.spec <<")"; 
marci@409
   915
      return os; 
marci@409
   916
    }
marci@435
   917
//  template<typename G> 
marci@435
   918
    friend std::ostream& 
marci@435
   919
    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Edge& i) { 
marci@409
   920
      os << "(edge: " << typename Graph::Edge(i) << " spec: " << i.spec << 
marci@409
   921
	" node: " << i.n << ")"; 
marci@409
   922
      return os; 
marci@409
   923
    }
marci@409
   924
marci@379
   925
  };
marci@379
   926
alpar@406
   927
  ///@}
marci@341
   928
alpar@921
   929
} //namespace lemon
marci@76
   930
alpar@406
   931
alpar@921
   932
#endif //LEMON_BIPARTITE_GRAPH_WRAPPER_H
marci@76
   933