src/work/peter/path/path.h
changeset 1327 ecc1cdea2ee7
parent 959 c80ef5912903
equal deleted inserted replaced
2:bb8f06548d9d 3:03cf4578ff9a
   106     /// \brief Starting point of the path.
   106     /// \brief Starting point of the path.
   107     ///
   107     ///
   108     /// Starting point of the path.
   108     /// Starting point of the path.
   109     /// Returns INVALID if the path is empty.
   109     /// Returns INVALID if the path is empty.
   110     GraphNode from() const {
   110     GraphNode from() const {
   111       return empty() ? INVALID : gr->tail(edges[0]);
   111       return empty() ? INVALID : gr->source(edges[0]);
   112     }
   112     }
   113     /// \brief End point of the path.
   113     /// \brief End point of the path.
   114     ///
   114     ///
   115     /// End point of the path.
   115     /// End point of the path.
   116     /// Returns INVALID if the path is empty.
   116     /// Returns INVALID if the path is empty.
   117     GraphNode to() const {
   117     GraphNode to() const {
   118       return empty() ? INVALID : gr->head(edges[length()-1]);
   118       return empty() ? INVALID : gr->target(edges[length()-1]);
   119     }
   119     }
   120 
   120 
   121     /// \brief Initializes node or edge iterator to point to the first
   121     /// \brief Initializes node or edge iterator to point to the first
   122     /// node or edge.
   122     /// node or edge.
   123     ///
   123     ///
   151       if( DM::range_check && !e.valid() )
   151       if( DM::range_check && !e.valid() )
   152 	fault("DirPath::next() on invalid iterator");
   152 	fault("DirPath::next() on invalid iterator");
   153       return ++e;
   153       return ++e;
   154     }
   154     }
   155 
   155 
   156     /// \brief Returns node iterator pointing to the head node of the
   156     /// \brief Returns node iterator pointing to the target node of the
   157     /// given edge iterator.
   157     /// given edge iterator.
   158     NodeIt head(const EdgeIt& e) const {
   158     NodeIt target(const EdgeIt& e) const {
   159       if( DM::range_check && !e.valid() )
   159       if( DM::range_check && !e.valid() )
   160 	fault("DirPath::head() on invalid iterator");
   160 	fault("DirPath::target() on invalid iterator");
   161       return NodeIt(*this, e.idx+1);
   161       return NodeIt(*this, e.idx+1);
   162     }
   162     }
   163 
   163 
   164     /// \brief Returns node iterator pointing to the tail node of the
   164     /// \brief Returns node iterator pointing to the source node of the
   165     /// given edge iterator.
   165     /// given edge iterator.
   166     NodeIt tail(const EdgeIt& e) const {
   166     NodeIt source(const EdgeIt& e) const {
   167       if( DM::range_check && !e.valid() )
   167       if( DM::range_check && !e.valid() )
   168 	fault("DirPath::tail() on invalid iterator");
   168 	fault("DirPath::source() on invalid iterator");
   169       return NodeIt(*this, e.idx);
   169       return NodeIt(*this, e.idx);
   170     }
   170     }
   171 
   171 
   172 
   172 
   173     /* Iterator classes */
   173     /* Iterator classes */
   252       ///Conversion to Graph::Node
   252       ///Conversion to Graph::Node
   253       operator const GraphNode& () const {
   253       operator const GraphNode& () const {
   254 	if(idx >= p->length())
   254 	if(idx >= p->length())
   255 	  return p->to();
   255 	  return p->to();
   256 	else if(idx >= 0)
   256 	else if(idx >= 0)
   257 	  return p->gr->tail(p->edges[idx]);
   257 	  return p->gr->source(p->edges[idx]);
   258 	else
   258 	else
   259 	  return INVALID;
   259 	  return INVALID;
   260       }
   260       }
   261       /// Next node
   261       /// Next node
   262       NodeIt& operator++() { ++idx; validate(); return *this; }
   262       NodeIt& operator++() { ++idx; validate(); return *this; }
   310       ///Push a new edge to the front of the path
   310       ///Push a new edge to the front of the path
   311 
   311 
   312       ///Push a new edge to the front of the path.
   312       ///Push a new edge to the front of the path.
   313       ///\sa setStartNode
   313       ///\sa setStartNode
   314       void pushFront(const GraphEdge& e) {
   314       void pushFront(const GraphEdge& e) {
   315 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
   315 	if( DM::consistensy_check && !empty() && P.gr->target(e)!=from() ) {
   316 	  fault("DirPath::Builder::pushFront: nonincident edge");
   316 	  fault("DirPath::Builder::pushFront: nonincident edge");
   317 	}
   317 	}
   318 	front.push_back(e);
   318 	front.push_back(e);
   319       }
   319       }
   320 
   320 
   321       ///Push a new edge to the back of the path
   321       ///Push a new edge to the back of the path
   322 
   322 
   323       ///Push a new edge to the back of the path.
   323       ///Push a new edge to the back of the path.
   324       ///\sa setStartNode
   324       ///\sa setStartNode
   325       void pushBack(const GraphEdge& e) {
   325       void pushBack(const GraphEdge& e) {
   326 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
   326 	if( DM::consistensy_check && !empty() && P.gr->source(e)!=to() ) {
   327 	  fault("DirPath::Builder::pushBack: nonincident edge");
   327 	  fault("DirPath::Builder::pushBack: nonincident edge");
   328 	}
   328 	}
   329 	back.push_back(e);
   329 	back.push_back(e);
   330       }
   330       }
   331 
   331 
   360 	return front.empty() && back.empty() && P.empty();
   360 	return front.empty() && back.empty() && P.empty();
   361       }
   361       }
   362 
   362 
   363       GraphNode from() const {
   363       GraphNode from() const {
   364 	if( ! front.empty() )
   364 	if( ! front.empty() )
   365 	  return P.gr->tail(front[front.size()-1]);
   365 	  return P.gr->source(front[front.size()-1]);
   366 	else if( ! P.empty() )
   366 	else if( ! P.empty() )
   367 	  return P.gr->tail(P.edges[0]);
   367 	  return P.gr->source(P.edges[0]);
   368 	else if( ! back.empty() )
   368 	else if( ! back.empty() )
   369 	  return P.gr->tail(back[0]);
   369 	  return P.gr->source(back[0]);
   370 	else
   370 	else
   371 	  return INVALID;
   371 	  return INVALID;
   372       }
   372       }
   373       GraphNode to() const {
   373       GraphNode to() const {
   374 	if( ! back.empty() )
   374 	if( ! back.empty() )
   375 	  return P.gr->head(back[back.size()-1]);
   375 	  return P.gr->target(back[back.size()-1]);
   376 	else if( ! P.empty() )
   376 	else if( ! P.empty() )
   377 	  return P.gr->head(P.edges[P.length()-1]);
   377 	  return P.gr->target(P.edges[P.length()-1]);
   378 	else if( ! front.empty() )
   378 	else if( ! front.empty() )
   379 	  return P.gr->head(front[0]);
   379 	  return P.gr->target(front[0]);
   380 	else
   380 	else
   381 	  return INVALID;
   381 	  return INVALID;
   382       }
   382       }
   383 
   383 
   384     };
   384     };
   469     /// \brief Starting point of the path.
   469     /// \brief Starting point of the path.
   470     ///
   470     ///
   471     /// Starting point of the path.
   471     /// Starting point of the path.
   472     /// Returns INVALID if the path is empty.
   472     /// Returns INVALID if the path is empty.
   473     GraphNode from() const {
   473     GraphNode from() const {
   474       return empty() ? INVALID : gr->tail(edges[0]);
   474       return empty() ? INVALID : gr->source(edges[0]);
   475     }
   475     }
   476     /// \brief End point of the path.
   476     /// \brief End point of the path.
   477     ///
   477     ///
   478     /// End point of the path.
   478     /// End point of the path.
   479     /// Returns INVALID if the path is empty.
   479     /// Returns INVALID if the path is empty.
   480     GraphNode to() const {
   480     GraphNode to() const {
   481       return empty() ? INVALID : gr->head(edges[length()-1]);
   481       return empty() ? INVALID : gr->target(edges[length()-1]);
   482     }
   482     }
   483 
   483 
   484     /// \brief Initializes node or edge iterator to point to the first
   484     /// \brief Initializes node or edge iterator to point to the first
   485     /// node or edge.
   485     /// node or edge.
   486     ///
   486     ///
   514       if( DM::range_check && !e.valid() )
   514       if( DM::range_check && !e.valid() )
   515 	fault("UndirPath::next() on invalid iterator");
   515 	fault("UndirPath::next() on invalid iterator");
   516       return ++e;
   516       return ++e;
   517     }
   517     }
   518 
   518 
   519     /// \brief Returns node iterator pointing to the head node of the
   519     /// \brief Returns node iterator pointing to the target node of the
   520     /// given edge iterator.
   520     /// given edge iterator.
   521     NodeIt head(const EdgeIt& e) const {
   521     NodeIt target(const EdgeIt& e) const {
   522       if( DM::range_check && !e.valid() )
   522       if( DM::range_check && !e.valid() )
   523 	fault("UndirPath::head() on invalid iterator");
   523 	fault("UndirPath::target() on invalid iterator");
   524       return NodeIt(*this, e.idx+1);
   524       return NodeIt(*this, e.idx+1);
   525     }
   525     }
   526 
   526 
   527     /// \brief Returns node iterator pointing to the tail node of the
   527     /// \brief Returns node iterator pointing to the source node of the
   528     /// given edge iterator.
   528     /// given edge iterator.
   529     NodeIt tail(const EdgeIt& e) const {
   529     NodeIt source(const EdgeIt& e) const {
   530       if( DM::range_check && !e.valid() )
   530       if( DM::range_check && !e.valid() )
   531 	fault("UndirPath::tail() on invalid iterator");
   531 	fault("UndirPath::source() on invalid iterator");
   532       return NodeIt(*this, e.idx);
   532       return NodeIt(*this, e.idx);
   533     }
   533     }
   534 
   534 
   535 
   535 
   536 
   536 
   613       ///Conversion to Graph::Node
   613       ///Conversion to Graph::Node
   614       operator const GraphNode& () const {
   614       operator const GraphNode& () const {
   615 	if(idx >= p->length())
   615 	if(idx >= p->length())
   616 	  return p->to();
   616 	  return p->to();
   617 	else if(idx >= 0)
   617 	else if(idx >= 0)
   618 	  return p->gr->tail(p->edges[idx]);
   618 	  return p->gr->source(p->edges[idx]);
   619 	else
   619 	else
   620 	  return INVALID;
   620 	  return INVALID;
   621       }
   621       }
   622       /// Next node
   622       /// Next node
   623       NodeIt& operator++() { ++idx; validate(); return *this; }
   623       NodeIt& operator++() { ++idx; validate(); return *this; }
   671       ///Push a new edge to the front of the path
   671       ///Push a new edge to the front of the path
   672 
   672 
   673       ///Push a new edge to the front of the path.
   673       ///Push a new edge to the front of the path.
   674       ///\sa setStartNode
   674       ///\sa setStartNode
   675       void pushFront(const GraphEdge& e) {
   675       void pushFront(const GraphEdge& e) {
   676 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
   676 	if( DM::consistensy_check && !empty() && P.gr->target(e)!=from() ) {
   677 	  fault("UndirPath::Builder::pushFront: nonincident edge");
   677 	  fault("UndirPath::Builder::pushFront: nonincident edge");
   678 	}
   678 	}
   679 	front.push_back(e);
   679 	front.push_back(e);
   680       }
   680       }
   681 
   681 
   682       ///Push a new edge to the back of the path
   682       ///Push a new edge to the back of the path
   683 
   683 
   684       ///Push a new edge to the back of the path.
   684       ///Push a new edge to the back of the path.
   685       ///\sa setStartNode
   685       ///\sa setStartNode
   686       void pushBack(const GraphEdge& e) {
   686       void pushBack(const GraphEdge& e) {
   687 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
   687 	if( DM::consistensy_check && !empty() && P.gr->source(e)!=to() ) {
   688 	  fault("UndirPath::Builder::pushBack: nonincident edge");
   688 	  fault("UndirPath::Builder::pushBack: nonincident edge");
   689 	}
   689 	}
   690 	back.push_back(e);
   690 	back.push_back(e);
   691       }
   691       }
   692 
   692 
   721 	return front.empty() && back.empty() && P.empty();
   721 	return front.empty() && back.empty() && P.empty();
   722       }
   722       }
   723 
   723 
   724       GraphNode from() const {
   724       GraphNode from() const {
   725 	if( ! front.empty() )
   725 	if( ! front.empty() )
   726 	  return P.gr->tail(front[front.size()-1]);
   726 	  return P.gr->source(front[front.size()-1]);
   727 	else if( ! P.empty() )
   727 	else if( ! P.empty() )
   728 	  return P.gr->tail(P.edges[0]);
   728 	  return P.gr->source(P.edges[0]);
   729 	else if( ! back.empty() )
   729 	else if( ! back.empty() )
   730 	  return P.gr->tail(back[0]);
   730 	  return P.gr->source(back[0]);
   731 	else
   731 	else
   732 	  return INVALID;
   732 	  return INVALID;
   733       }
   733       }
   734       GraphNode to() const {
   734       GraphNode to() const {
   735 	if( ! back.empty() )
   735 	if( ! back.empty() )
   736 	  return P.gr->head(back[back.size()-1]);
   736 	  return P.gr->target(back[back.size()-1]);
   737 	else if( ! P.empty() )
   737 	else if( ! P.empty() )
   738 	  return P.gr->head(P.edges[P.length()-1]);
   738 	  return P.gr->target(P.edges[P.length()-1]);
   739 	else if( ! front.empty() )
   739 	else if( ! front.empty() )
   740 	  return P.gr->head(front[0]);
   740 	  return P.gr->target(front[0]);
   741 	else
   741 	else
   742 	  return INVALID;
   742 	  return INVALID;
   743       }
   743       }
   744 
   744 
   745     };
   745     };
   838     bool pushFront(const GraphEdge &e);
   838     bool pushFront(const GraphEdge &e);
   839     bool pushBack(const GraphEdge &e);
   839     bool pushBack(const GraphEdge &e);
   840     bool setFrom(const GraphNode &n);
   840     bool setFrom(const GraphNode &n);
   841     bool setTo(const GraphNode &n);
   841     bool setTo(const GraphNode &n);
   842 
   842 
   843     // WARNING: these two functions return the head/tail of an edge with
   843     // WARNING: these two functions return the target/source of an edge with
   844     // respect to the direction of the path!
   844     // respect to the direction of the path!
   845     // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if 
   845     // So G.target(P.graphEdge(e)) == P.graphNode(P.target(e)) holds only if 
   846     // P.forward(e) is true (or the edge is a loop)!
   846     // P.forward(e) is true (or the edge is a loop)!
   847     NodeIt head(const EdgeIt& e) const;
   847     NodeIt target(const EdgeIt& e) const;
   848     NodeIt tail(const EdgeIt& e) const;
   848     NodeIt source(const EdgeIt& e) const;
   849 
   849 
   850     // FIXME: ezeknek valami jobb nev kellene!!!
   850     // FIXME: ezeknek valami jobb nev kellene!!!
   851     GraphEdge graphEdge(const EdgeIt& e) const;
   851     GraphEdge graphEdge(const EdgeIt& e) const;
   852     GraphNode graphNode(const NodeIt& n) const;
   852     GraphNode graphNode(const NodeIt& n) const;
   853 
   853 
   871 
   871 
   872     class NodeIt {
   872     class NodeIt {
   873       friend class DynamicPath;
   873       friend class DynamicPath;
   874 
   874 
   875       size_t idx;
   875       size_t idx;
   876       bool tail;  // Is this node the tail of the edge with same idx?
   876       bool source;  // Is this node the source of the edge with same idx?
   877 
   877 
   878     public:
   878     public:
   879       // FIXME: jarna neki ilyen is...
   879       // FIXME: jarna neki ilyen is...
   880       // NodeIt(Invalid);
   880       // NodeIt(Invalid);
   881 
   881 
   894   typename DynamicPath<Gr>::EdgeIt&
   894   typename DynamicPath<Gr>::EdgeIt&
   895   DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const {
   895   DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const {
   896     if( e.it == edges.end() ) 
   896     if( e.it == edges.end() ) 
   897       return e;
   897       return e;
   898 
   898 
   899     GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) );
   899     GraphNode common_node = ( e.forw ? G.target(*e.it) : G.source(*e.it) );
   900     ++e.it;
   900     ++e.it;
   901 
   901 
   902     // Invalid edgeit is always forward :)
   902     // Invalid edgeit is always forward :)
   903     if( e.it == edges.end() ) {
   903     if( e.it == edges.end() ) {
   904       e.forw = true;
   904       e.forw = true;
   905       return e;
   905       return e;
   906     }
   906     }
   907 
   907 
   908     e.forw = ( G.tail(*e.it) == common_node );
   908     e.forw = ( G.source(*e.it) == common_node );
   909     return e;
   909     return e;
   910   }
   910   }
   911 
   911 
   912   template<typename Gr>
   912   template<typename Gr>
   913   typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const {
   913   typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const {
   916       n.idx = length()+1;
   916       n.idx = length()+1;
   917       return n;
   917       return n;
   918     }
   918     }
   919 
   919 
   920     
   920     
   921     GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) :
   921     GraphNode next_node = ( n.source ? G.target(edges[n.idx]) :
   922 			      G.tail(edges[n.idx]) );
   922 			      G.source(edges[n.idx]) );
   923     ++n.idx;
   923     ++n.idx;
   924     if( n.idx < length() ) {
   924     if( n.idx < length() ) {
   925       n.tail = ( next_node == G.tail(edges[n.idx]) );
   925       n.source = ( next_node == G.source(edges[n.idx]) );
   926     }
   926     }
   927     else {
   927     else {
   928       n.tail = true;
   928       n.source = true;
   929     }
   929     }
   930 
   930 
   931     return n;
   931     return n;
   932   }
   932   }
   933 
   933 
   934   template<typename Gr>
   934   template<typename Gr>
   935   bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a,
   935   bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a,
   936 			  GraphNode &b) {
   936 			  GraphNode &b) {
   937     if( G.tail(e) == a ) {
   937     if( G.source(e) == a ) {
   938       b=G.head(e);
   938       b=G.target(e);
   939       return true;
   939       return true;
   940     }
   940     }
   941     if( G.head(e) == a ) {
   941     if( G.target(e) == a ) {
   942       b=G.tail(e);
   942       b=G.source(e);
   943       return true;
   943       return true;
   944     }
   944     }
   945     return false;
   945     return false;
   946   }
   946   }
   947 
   947 
   948   template<typename Gr>
   948   template<typename Gr>
   949   bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e,
   949   bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e,
   950 			     const GraphEdge &f) {
   950 			     const GraphEdge &f) {
   951     if( edgeIncident(f, G.tail(e), _last) ) {
   951     if( edgeIncident(f, G.source(e), _last) ) {
   952       _first = G.head(e);
   952       _first = G.target(e);
   953       return true;
   953       return true;
   954     }
   954     }
   955     if( edgeIncident(f, G.head(e), _last) ) {
   955     if( edgeIncident(f, G.target(e), _last) ) {
   956       _first = G.tail(e);
   956       _first = G.source(e);
   957       return true;
   957       return true;
   958     }
   958     }
   959     return false;
   959     return false;
   960   }
   960   }
   961 
   961 
  1037   }
  1037   }
  1038 
  1038 
  1039 
  1039 
  1040   template<typename Gr>
  1040   template<typename Gr>
  1041   typename DynamicPath<Gr>::NodeIt
  1041   typename DynamicPath<Gr>::NodeIt
  1042   DynamicPath<Gr>::tail(const EdgeIt& e) const {
  1042   DynamicPath<Gr>::source(const EdgeIt& e) const {
  1043     NodeIt n;
  1043     NodeIt n;
  1044 
  1044 
  1045     if( e.it == edges.end() ) {
  1045     if( e.it == edges.end() ) {
  1046       // FIXME: invalid-> invalid
  1046       // FIXME: invalid-> invalid
  1047       n.idx = length() + 1;
  1047       n.idx = length() + 1;
  1048       n.tail = true;
  1048       n.source = true;
  1049       return n;
  1049       return n;
  1050     }
  1050     }
  1051 
  1051 
  1052     n.idx = e.it-edges.begin();
  1052     n.idx = e.it-edges.begin();
  1053     n.tail = e.forw;
  1053     n.source = e.forw;
  1054     return n;
  1054     return n;
  1055   }
  1055   }
  1056 
  1056 
  1057   template<typename Gr>
  1057   template<typename Gr>
  1058   typename DynamicPath<Gr>::NodeIt
  1058   typename DynamicPath<Gr>::NodeIt
  1059   DynamicPath<Gr>::head(const EdgeIt& e) const {
  1059   DynamicPath<Gr>::target(const EdgeIt& e) const {
  1060     if( e.it == edges.end()-1 ) {
  1060     if( e.it == edges.end()-1 ) {
  1061       return _last;
  1061       return _last;
  1062     }
  1062     }
  1063 
  1063 
  1064     EdgeIt next_edge = e;
  1064     EdgeIt next_edge = e;
  1065     next(next_edge);
  1065     next(next_edge);
  1066     return tail(next_edge);
  1066     return source(next_edge);
  1067   }
  1067   }
  1068       
  1068       
  1069   template<typename Gr>
  1069   template<typename Gr>
  1070   typename DynamicPath<Gr>::GraphEdge
  1070   typename DynamicPath<Gr>::GraphEdge
  1071   DynamicPath<Gr>::graphEdge(const EdgeIt& e) const {
  1071   DynamicPath<Gr>::graphEdge(const EdgeIt& e) const {
  1079   
  1079   
  1080   template<typename Gr>
  1080   template<typename Gr>
  1081   typename DynamicPath<Gr>::GraphNode
  1081   typename DynamicPath<Gr>::GraphNode
  1082   DynamicPath<Gr>::graphNode(const NodeIt& n) const {
  1082   DynamicPath<Gr>::graphNode(const NodeIt& n) const {
  1083     if( n.idx < length() ) {
  1083     if( n.idx < length() ) {
  1084       return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]);
  1084       return n.source ? G.source(edges[n.idx]) : G.target(edges[n.idx]);
  1085     }
  1085     }
  1086     else if( n.idx == length() ) {
  1086     else if( n.idx == length() ) {
  1087       return _last;
  1087       return _last;
  1088     }
  1088     }
  1089     else {
  1089     else {
  1101       return e;
  1101       return e;
  1102     }
  1102     }
  1103 
  1103 
  1104     e.it = edges.begin()+k;
  1104     e.it = edges.begin()+k;
  1105     if(k==0) {
  1105     if(k==0) {
  1106       e.forw = ( G.tail(*e.it) == _first );
  1106       e.forw = ( G.source(*e.it) == _first );
  1107     }
  1107     }
  1108     else {
  1108     else {
  1109       e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) ||
  1109       e.forw = ( G.source(*e.it) == G.source(edges[k-1]) ||
  1110 		 G.tail(*e.it) == G.head(edges[k-1]) );
  1110 		 G.source(*e.it) == G.target(edges[k-1]) );
  1111     }
  1111     }
  1112     return e;
  1112     return e;
  1113   }
  1113   }
  1114     
  1114     
  1115   template<typename Gr>
  1115   template<typename Gr>
  1116   typename DynamicPath<Gr>::NodeIt&
  1116   typename DynamicPath<Gr>::NodeIt&
  1117   DynamicPath<Gr>::nth(NodeIt &n, size_t k) const {
  1117   DynamicPath<Gr>::nth(NodeIt &n, size_t k) const {
  1118     if( k>length() ) {
  1118     if( k>length() ) {
  1119       // FIXME: invalid NodeIt
  1119       // FIXME: invalid NodeIt
  1120       n.idx = length()+1;
  1120       n.idx = length()+1;
  1121       n.tail = true;
  1121       n.source = true;
  1122       return n;
  1122       return n;
  1123     }
  1123     }
  1124     if( k==length() ) {
  1124     if( k==length() ) {
  1125       n.idx = length();
  1125       n.idx = length();
  1126       n.tail = true;
  1126       n.source = true;
  1127       return n;
  1127       return n;
  1128     }
  1128     }
  1129     n = tail(nth<EdgeIt>(k));
  1129     n = source(nth<EdgeIt>(k));
  1130     return n;
  1130     return n;
  1131   }
  1131   }
  1132 
  1132 
  1133   // Reszut konstruktorok:
  1133   // Reszut konstruktorok:
  1134 
  1134 
  1137   DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a,
  1137   DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a,
  1138 			       const EdgeIt &b) :
  1138 			       const EdgeIt &b) :
  1139     G(P.G), edges(a.it, b.it)    // WARNING: if b.it < a.it this will blow up! 
  1139     G(P.G), edges(a.it, b.it)    // WARNING: if b.it < a.it this will blow up! 
  1140   {
  1140   {
  1141     if( G.valid(P._first) && a.it < P.edges.end() ) {
  1141     if( G.valid(P._first) && a.it < P.edges.end() ) {
  1142       _first = ( a.forw ? G.tail(*a.it) : G.head(*a.it) );
  1142       _first = ( a.forw ? G.source(*a.it) : G.target(*a.it) );
  1143       if( b.it < P.edges.end() ) {
  1143       if( b.it < P.edges.end() ) {
  1144 	_last = ( b.forw ? G.tail(*b.it) : G.head(*b.it) );
  1144 	_last = ( b.forw ? G.source(*b.it) : G.target(*b.it) );
  1145       }
  1145       }
  1146       else {
  1146       else {
  1147 	_last = P._last;
  1147 	_last = P._last;
  1148       }
  1148       }
  1149     }
  1149     }