COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2160:abd867cf8a9c

Last change on this file since 2160:abd867cf8a9c was 2160:abd867cf8a9c, checked in by Balazs Dezso, 18 years ago

Change source and target for the bipartite list graph
Some documentation corrections

File size: 39.0 KB
RevLine 
[948]1/* -*- C++ -*-
2 *
[1956]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1359]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[948]8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
[395]18
[921]19#ifndef LEMON_LIST_GRAPH_H
20#define LEMON_LIST_GRAPH_H
[395]21
[948]22///\ingroup graphs
23///\file
[2116]24///\brief ListGraph, ListUGraph classes.
[948]25
[2116]26#include <lemon/bits/base_extender.h>
[1791]27#include <lemon/bits/graph_extender.h>
[782]28
[2116]29#include <lemon/error.h>
30
[1979]31#include <vector>
[1011]32#include <list>
[782]33
[921]34namespace lemon {
[395]35
[946]36  class ListGraphBase {
[406]37
[949]38  protected:
[946]39    struct NodeT {
[1470]40      int first_in, first_out;
[397]41      int prev, next;
[395]42    };
[946]43 
44    struct EdgeT {
[986]45      int target, source;
[397]46      int prev_in, prev_out;
47      int next_in, next_out;
[395]48    };
49
50    std::vector<NodeT> nodes;
[946]51
[397]52    int first_node;
[946]53
[397]54    int first_free_node;
[946]55
[395]56    std::vector<EdgeT> edges;
[946]57
[397]58    int first_free_edge;
[395]59   
[782]60  public:
[395]61   
[946]62    typedef ListGraphBase Graph;
[397]63   
[946]64    class Node {
[975]65      friend class ListGraphBase;
[946]66    protected:
[395]67
[946]68      int id;
[2031]69      explicit Node(int pid) { id = pid;}
[395]70
[946]71    public:
72      Node() {}
73      Node (Invalid) { id = -1; }
74      bool operator==(const Node& node) const {return id == node.id;}
75      bool operator!=(const Node& node) const {return id != node.id;}
76      bool operator<(const Node& node) const {return id < node.id;}
77    };
[782]78
[946]79    class Edge {
[975]80      friend class ListGraphBase;
[946]81    protected:
[782]82
[946]83      int id;
[2031]84      explicit Edge(int pid) { id = pid;}
[395]85
[946]86    public:
87      Edge() {}
88      Edge (Invalid) { id = -1; }
89      bool operator==(const Edge& edge) const {return id == edge.id;}
90      bool operator!=(const Edge& edge) const {return id != edge.id;}
91      bool operator<(const Edge& edge) const {return id < edge.id;}
92    };
93
94
95
96    ListGraphBase()
[782]97      : nodes(), first_node(-1),
98        first_free_node(-1), edges(), first_free_edge(-1) {}
99
[395]100   
[813]101    /// Maximum node ID.
102   
103    /// Maximum node ID.
104    ///\sa id(Node)
[1791]105    int maxNodeId() const { return nodes.size()-1; }
[946]106
[813]107    /// Maximum edge ID.
108   
109    /// Maximum edge ID.
110    ///\sa id(Edge)
[1791]111    int maxEdgeId() const { return edges.size()-1; }
[395]112
[2031]113    Node source(Edge e) const { return Node(edges[e.id].source); }
114    Node target(Edge e) const { return Node(edges[e.id].target); }
[395]115
116
[946]117    void first(Node& node) const {
118      node.id = first_node;
119    }
120
121    void next(Node& node) const {
122      node.id = nodes[node.id].next;
123    }
124
125
126    void first(Edge& e) const {
127      int n;
128      for(n = first_node;
129          n!=-1 && nodes[n].first_in == -1;
130          n = nodes[n].next);
131      e.id = (n == -1) ? -1 : nodes[n].first_in;
132    }
133
134    void next(Edge& edge) const {
135      if (edges[edge.id].next_in != -1) {
136        edge.id = edges[edge.id].next_in;
137      } else {
138        int n;
[986]139        for(n = nodes[edges[edge.id].target].next;
[946]140          n!=-1 && nodes[n].first_in == -1;
141          n = nodes[n].next);
142        edge.id = (n == -1) ? -1 : nodes[n].first_in;
143      }     
144    }
145
146    void firstOut(Edge &e, const Node& v) const {
147      e.id = nodes[v.id].first_out;
148    }
149    void nextOut(Edge &e) const {
150      e.id=edges[e.id].next_out;
151    }
152
153    void firstIn(Edge &e, const Node& v) const {
154      e.id = nodes[v.id].first_in;
155    }
156    void nextIn(Edge &e) const {
157      e.id=edges[e.id].next_in;
158    }
159
[813]160   
[946]161    static int id(Node v) { return v.id; }
162    static int id(Edge e) { return e.id; }
[395]163
[1791]164    static Node nodeFromId(int id) { return Node(id);}
165    static Edge edgeFromId(int id) { return Edge(id);}
[1106]166
[397]167    /// Adds a new node to the graph.
168
[2123]169    /// Adds a new node to the graph.
170    ///
[813]171    /// \warning It adds the new node to the front of the list.
[397]172    /// (i.e. the lastly added node becomes the first.)
[946]173    Node addNode() {     
[397]174      int n;
175     
[946]176      if(first_free_node==-1) {
177        n = nodes.size();
178        nodes.push_back(NodeT());
179      } else {
[397]180        n = first_free_node;
181        first_free_node = nodes[n].next;
182      }
183     
184      nodes[n].next = first_node;
185      if(first_node != -1) nodes[first_node].prev = n;
186      first_node = n;
187      nodes[n].prev = -1;
188     
189      nodes[n].first_in = nodes[n].first_out = -1;
190     
[946]191      return Node(n);
[395]192    }
193   
194    Edge addEdge(Node u, Node v) {
[946]195      int n;     
196
197      if (first_free_edge == -1) {
198        n = edges.size();
199        edges.push_back(EdgeT());
200      } else {
[397]201        n = first_free_edge;
202        first_free_edge = edges[n].next_in;
203      }
204     
[986]205      edges[n].source = u.id;
206      edges[n].target = v.id;
[395]207
[946]208      edges[n].next_out = nodes[u.id].first_out;
209      if(nodes[u.id].first_out != -1) {
210        edges[nodes[u.id].first_out].prev_out = n;
211      }
212     
213      edges[n].next_in = nodes[v.id].first_in;
214      if(nodes[v.id].first_in != -1) {
215        edges[nodes[v.id].first_in].prev_in = n;
216      }
217     
[397]218      edges[n].prev_in = edges[n].prev_out = -1;
219       
[946]220      nodes[u.id].first_out = nodes[v.id].first_in = n;
[397]221
[946]222      return Edge(n);
[395]223    }
[774]224   
[946]225    void erase(const Node& node) {
226      int n = node.id;
227     
228      if(nodes[n].next != -1) {
229        nodes[nodes[n].next].prev = nodes[n].prev;
230      }
231     
232      if(nodes[n].prev != -1) {
233        nodes[nodes[n].prev].next = nodes[n].next;
234      } else {
235        first_node = nodes[n].next;
236      }
237     
238      nodes[n].next = first_free_node;
239      first_free_node = n;
[395]240
[774]241    }
242   
[946]243    void erase(const Edge& edge) {
244      int n = edge.id;
[397]245     
[946]246      if(edges[n].next_in!=-1) {
[397]247        edges[edges[n].next_in].prev_in = edges[n].prev_in;
[946]248      }
249
250      if(edges[n].prev_in!=-1) {
[397]251        edges[edges[n].prev_in].next_in = edges[n].next_in;
[946]252      } else {
[986]253        nodes[edges[n].target].first_in = edges[n].next_in;
[946]254      }
255
[397]256     
[946]257      if(edges[n].next_out!=-1) {
[397]258        edges[edges[n].next_out].prev_out = edges[n].prev_out;
[946]259      }
260
261      if(edges[n].prev_out!=-1) {
[397]262        edges[edges[n].prev_out].next_out = edges[n].next_out;
[946]263      } else {
[986]264        nodes[edges[n].source].first_out = edges[n].next_out;
[946]265      }
[397]266     
267      edges[n].next_in = first_free_edge;
[695]268      first_free_edge = n;     
[397]269
270    }
271
272    void clear() {
[782]273      edges.clear();
274      nodes.clear();
[946]275      first_node = first_free_node = first_free_edge = -1;
[937]276    }
277
[949]278  protected:
[2111]279    void changeTarget(Edge e, Node n)
[949]280    {
281      if(edges[e.id].next_in != -1)
282        edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
283      if(edges[e.id].prev_in != -1)
284        edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
[986]285      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
[1702]286      if (nodes[n.id].first_in != -1) {
287        edges[nodes[n.id].first_in].prev_in = e.id;
288      }
[986]289      edges[e.id].target = n.id;
[949]290      edges[e.id].prev_in = -1;
291      edges[e.id].next_in = nodes[n.id].first_in;
292      nodes[n.id].first_in = e.id;
293    }
[2111]294    void changeSource(Edge e, Node n)
[949]295    {
296      if(edges[e.id].next_out != -1)
297        edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
298      if(edges[e.id].prev_out != -1)
299        edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
[986]300      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
[1702]301      if (nodes[n.id].first_out != -1) {
302        edges[nodes[n.id].first_out].prev_out = e.id;
303      }
[986]304      edges[e.id].source = n.id;
[949]305      edges[e.id].prev_out = -1;
306      edges[e.id].next_out = nodes[n.id].first_out;
307      nodes[n.id].first_out = e.id;
308    }
309
[919]310  };
[909]311
[1979]312  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
[400]313
[2116]314  /// \addtogroup graphs
315  /// @{
[400]316
[948]317  ///A list graph class.
[400]318
[2117]319  ///This is a simple and fast graph implementation.
[948]320  ///
[2117]321  ///It conforms to the \ref concept::Graph "Graph concept" and it
[2111]322  ///also provides several additional useful extra functionalities.
323  ///The most of the member functions and nested classes are
324  ///documented only in the concept class.
325  ///\sa concept::Graph.
[782]326
[1999]327  class ListGraph : public ExtendedListGraphBase {
[2128]328  private:
329    ///ListGraph is \e not copy constructible. Use GraphCopy() instead.
330   
331    ///ListGraph is \e not copy constructible. Use GraphCopy() instead.
332    ///
333    ListGraph(const ListGraph &) :ExtendedListGraphBase() {};
[2132]334    ///\brief Assignment of ListGraph to another one is \e not allowed.
[2128]335    ///Use GraphCopy() instead.
336
[2132]337    ///Assignment of ListGraph to another one is \e not allowed.
[2128]338    ///Use GraphCopy() instead.
339    void operator=(const ListGraph &) {}
[948]340  public:
[1999]341
342    typedef ExtendedListGraphBase Parent;
343
[2128]344    /// Constructor
345   
346    /// Constructor.
347    ///
348    ListGraph() {}
349
[2111]350    ///Add a new node to the graph.
351   
352    /// \return the new node.
353    ///
354    Node addNode() { return Parent::addNode(); }
355
356    ///Add a new edge to the graph.
357   
358    ///Add a new edge to the graph with source node \c s
359    ///and target node \c t.
360    ///\return the new edge.
361    Edge addEdge(const Node& s, const Node& t) {
362      return Parent::addEdge(s, t);
363    }
364
[1546]365    /// Changes the target of \c e to \c n
[948]366
[1546]367    /// Changes the target of \c e to \c n
[948]368    ///
[2160]369    ///\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s referencing
[2114]370    ///the changed edge remain valid. However <tt>InEdgeIt</tt>s are
371    ///invalidated.
[2123]372    ///\warning This functionality cannot be used together with the Snapshot
373    ///feature.
[1718]374    void changeTarget(Edge e, Node n) {
[2111]375      Parent::changeTarget(e,n);
[1718]376    }
[1546]377    /// Changes the source of \c e to \c n
[948]378
[1546]379    /// Changes the source of \c e to \c n
[948]380    ///
[2160]381    ///\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s referencing
[2114]382    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are
383    ///invalidated.
[2123]384    ///\warning This functionality cannot be used together with the Snapshot
385    ///feature.
[1718]386    void changeSource(Edge e, Node n) {
[2111]387      Parent::changeSource(e,n);
[1718]388    }
[949]389
[1010]390    /// Invert the direction of an edge.
391
[2160]392    ///\note The <tt>EdgeIt</tt>s referencing the changed edge remain
[2114]393    ///valid. However <tt>OutEdgeIt</tt>s and <tt>InEdgeIt</tt>s are
394    ///invalidated.
[2123]395    ///\warning This functionality cannot be used together with the Snapshot
396    ///feature.
[1010]397    void reverseEdge(Edge e) {
398      Node t=target(e);
[2111]399      changeTarget(e,source(e));
400      changeSource(e,t);
[1010]401    }
402
[2111]403    /// \brief Using this it is possible to avoid the superfluous memory
404    /// allocation.
[1010]405
[2107]406    ///Using this it is possible to avoid the superfluous memory
407    ///allocation: if you know that the graph you want to build will
[2123]408    ///contain at least 10 million nodes then it is worth reserving
[2107]409    ///space for this amount before starting to build the graph.
410    void reserveNode(int n) { nodes.reserve(n); };
411
[2111]412    /// \brief Using this it is possible to avoid the superfluous memory
413    /// allocation.
[2107]414
415    ///Using this it is possible to avoid the superfluous memory
416    ///allocation: see the \ref reserveNode function.
[949]417    void reserveEdge(int n) { edges.reserve(n); };
[1010]418
[2107]419
[1010]420    ///Contract two nodes.
421
422    ///This function contracts two nodes.
423    ///
424    ///Node \p b will be removed but instead of deleting
[2102]425    ///incident edges, they will be joined to \p a.
[1010]426    ///The last parameter \p r controls whether to remove loops. \c true
427    ///means that loops will be removed.
428    ///
[2160]429    ///\note The <tt>EdgeIt</tt>s
[1281]430    ///referencing a moved edge remain
[2160]431    ///valid. However <tt>InEdgeIt</tt>s and <tt>OutEdgeIt</tt>s
[1010]432    ///may be invalidated.
[2123]433    ///\warning This functionality cannot be used together with the Snapshot
434    ///feature.
[1718]435    void contract(Node a, Node b, bool r = true)
[1010]436    {
437      for(OutEdgeIt e(*this,b);e!=INVALID;) {
438        OutEdgeIt f=e;
439        ++f;
440        if(r && target(e)==a) erase(e);
[1546]441        else changeSource(e,a);
[1010]442        e=f;
443      }
444      for(InEdgeIt e(*this,b);e!=INVALID;) {
445        InEdgeIt f=e;
446        ++f;
447        if(r && source(e)==a) erase(e);
[1546]448        else changeTarget(e,a);
[1010]449        e=f;
450      }
451      erase(b);
452    }
[1011]453
[1281]454    ///Split a node.
[1011]455
[1284]456    ///This function splits a node. First a new node is added to the graph,
457    ///then the source of each outgoing edge of \c n is moved to this new node.
[1281]458    ///If \c connect is \c true (this is the default value), then a new edge
459    ///from \c n to the newly created node is also added.
460    ///\return The newly created node.
461    ///
[2160]462    ///\note The <tt>EdgeIt</tt>s referencing a moved edge remain
463    ///valid. However <tt>InEdgeIt</tt>s and <tt>OutEdgeIt</tt>s may
464    ///be invalidated. 
465    ///
466    ///\warning This functionality cannot be used together with the
467    ///Snapshot feature.  \todo It could be implemented in a bit
468    ///faster way.
[2114]469    Node split(Node n, bool connect = true) {
[1281]470      Node b = addNode();
471      for(OutEdgeIt e(*this,n);e!=INVALID;) {
472        OutEdgeIt f=e;
473        ++f;
[1546]474        changeSource(e,b);
[1281]475        e=f;
476      }
[2114]477      if (connect) addEdge(n,b);
[1281]478      return b;
479    }
480     
[1812]481    ///Split an edge.
482
[2102]483    ///This function splits an edge. First a new node \c b is added to
484    ///the graph, then the original edge is re-targeted to \c
485    ///b. Finally an edge from \c b to the original target is added.
486    ///\return The newly created node. 
487    ///\warning This functionality
488    ///cannot be used together with the Snapshot feature.
[2114]489    Node split(Edge e) {
[1812]490      Node b = addNode();
491      addEdge(b,target(e));
492      changeTarget(e,b);
493      return b;
494    }
495     
[2114]496    /// \brief Class to make a snapshot of the graph and restore
497    /// to it later.
[1011]498    ///
[2114]499    /// Class to make a snapshot of the graph and to restore it
500    /// later.
[1011]501    ///
[2114]502    /// The newly added nodes and edges can be removed using the
503    /// restore() function.
504    ///
505    /// \warning Edge and node deletions cannot be restored.
506    class Snapshot {
[1774]507    public:
508     
509      class UnsupportedOperation : public LogicError {
510      public:
[2151]511        virtual const char* what() const throw() {
[1774]512          return "lemon::ListGraph::Snapshot::UnsupportedOperation";
513        }
514      };
515           
516
[1999]517    protected:
[2114]518
519      typedef Parent::NodeNotifier NodeNotifier;
520
521      class NodeObserverProxy : public NodeNotifier::ObserverBase {
522      public:
523
524        NodeObserverProxy(Snapshot& _snapshot)
525          : snapshot(_snapshot) {}
526
527        using NodeNotifier::ObserverBase::attach;
528        using NodeNotifier::ObserverBase::detach;
529        using NodeNotifier::ObserverBase::attached;
530       
531      protected:
532       
533        virtual void add(const Node& node) {
534          snapshot.addNode(node);
535        }
536        virtual void add(const std::vector<Node>& nodes) {
537          for (int i = nodes.size() - 1; i >= 0; ++i) {
538            snapshot.addNode(nodes[i]);
539          }
540        }
541        virtual void erase(const Node& node) {
542          snapshot.eraseNode(node);
543        }
544        virtual void erase(const std::vector<Node>& nodes) {
545          for (int i = 0; i < (int)nodes.size(); ++i) {
546            if (!snapshot.eraseNode(nodes[i])) break;
547          }
548        }
549        virtual void build() {
550          NodeNotifier* notifier = getNotifier();
551          Node node;
552          std::vector<Node> nodes;
553          for (notifier->first(node); node != INVALID; notifier->next(node)) {
554            nodes.push_back(node);
555          }
556          for (int i = nodes.size() - 1; i >= 0; --i) {
557            snapshot.addNode(nodes[i]);
558          }
559        }
560        virtual void clear() {
561          NodeNotifier* notifier = getNotifier();
562          Node node;
563          for (notifier->first(node); node != INVALID; notifier->next(node)) {
564            if (!snapshot.eraseNode(node)) break;
565          }
566        }
567
568        Snapshot& snapshot;
569      };
570
571      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
572      public:
573
574        EdgeObserverProxy(Snapshot& _snapshot)
575          : snapshot(_snapshot) {}
576
577        using EdgeNotifier::ObserverBase::attach;
578        using EdgeNotifier::ObserverBase::detach;
579        using EdgeNotifier::ObserverBase::attached;
580       
581      protected:
582
583        virtual void add(const Edge& edge) {
584          snapshot.addEdge(edge);
585        }
586        virtual void add(const std::vector<Edge>& edges) {
587          for (int i = edges.size() - 1; i >= 0; ++i) {
588            snapshot.addEdge(edges[i]);
589          }
590        }
591        virtual void erase(const Edge& edge) {
592          snapshot.eraseEdge(edge);
593        }
594        virtual void erase(const std::vector<Edge>& edges) {
595          for (int i = 0; i < (int)edges.size(); ++i) {
596            if (!snapshot.eraseEdge(edges[i])) break;
597          }
598        }
599        virtual void build() {
600          EdgeNotifier* notifier = getNotifier();
601          Edge edge;
602          std::vector<Edge> edges;
603          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
604            edges.push_back(edge);
605          }
606          for (int i = edges.size() - 1; i >= 0; --i) {
607            snapshot.addEdge(edges[i]);
608          }
609        }
610        virtual void clear() {
611          EdgeNotifier* notifier = getNotifier();
612          Edge edge;
613          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
614            if (!snapshot.eraseEdge(edge)) break;
615          }
616        }
617
618        Snapshot& snapshot;
619      };
[1011]620     
[2114]621      ListGraph *graph;
622
623      NodeObserverProxy node_observer_proxy;
624      EdgeObserverProxy edge_observer_proxy;
625
[1011]626      std::list<Node> added_nodes;
627      std::list<Edge> added_edges;
[2114]628
629
630      void addNode(const Node& node) {
631        added_nodes.push_front(node);       
[1011]632      }
[2114]633      bool eraseNode(const Node& node) {
634        std::list<Node>::iterator it =
635          std::find(added_nodes.begin(), added_nodes.end(), node);
636        if (it == added_nodes.end()) {
637          clear();
638          return false;
639        } else {
640          added_nodes.erase(it);
641          return true;
642        }
[1011]643      }
644
[2114]645      void addEdge(const Edge& edge) {
646        added_edges.push_front(edge);       
647      }
648      bool eraseEdge(const Edge& edge) {
649        std::list<Edge>::iterator it =
650          std::find(added_edges.begin(), added_edges.end(), edge);
651        if (it == added_edges.end()) {
652          clear();
653          return false;
654        } else {
655          added_edges.erase(it);
656          return true;
657        }       
658      }
[1457]659
[2114]660      void attach(ListGraph &_graph) {
661        graph = &_graph;
662        node_observer_proxy.attach(graph->getNotifier(Node()));
663        edge_observer_proxy.attach(graph->getNotifier(Edge()));
[1011]664      }
665           
[2114]666      void detach() {
667        node_observer_proxy.detach();
668        edge_observer_proxy.detach();
669      }
670
671      void clear() {
672        detach();
673        added_nodes.clear();
674        added_edges.clear();       
[1011]675      }
[1774]676
[1011]677    public:
[2114]678
[2160]679      /// \brief Default constructor.
[2114]680      ///
681      /// Default constructor.
682      /// To actually make a snapshot you must call save().
683      Snapshot()
684        : graph(0), node_observer_proxy(*this),
685          edge_observer_proxy(*this) {}
[1011]686     
[2114]687      /// \brief Constructor that immediately makes a snapshot.
688      ///     
689      /// This constructor immediately makes a snapshot of the graph.
690      /// \param _graph The graph we make a snapshot of.
691      Snapshot(ListGraph &_graph)
692        : node_observer_proxy(*this),
693          edge_observer_proxy(*this) {
694        attach(_graph);
[1011]695      }
696     
[2114]697      /// \brief Make a snapshot.
[1011]698      ///
[2114]699      /// Make a snapshot of the graph.
700      ///
701      /// This function can be called more than once. In case of a repeated
702      /// call, the previous snapshot gets lost.
703      /// \param _graph The graph we make the snapshot of.
704      void save(ListGraph &_graph) {
705        clear();
706        attach(_graph);
[1011]707      }
708     
[2114]709      /// \brief Undo the changes until the last snapshot.
710      //
[2123]711      /// Undo the changes until the last snapshot created by save().
[1011]712      void restore() {
[2114]713        detach();
[1011]714        while(!added_edges.empty()) {
[2114]715          graph->erase(added_edges.front());
[1011]716          added_edges.pop_front();
717        }
718        while(!added_nodes.empty()) {
[2114]719          graph->erase(added_nodes.front());
[1011]720          added_nodes.pop_front();
721        }
722      }
[2114]723
724      /// \brief Gives back true when the snapshot is valid.
725      ///
726      /// Gives back true when the snapshot is valid.
727      bool valid() const {
728        return node_observer_proxy.attached();
729      }
[1011]730    };
731   
[949]732  };
[1034]733
[2116]734  ///@}
735
736  /**************** Undirected List Graph ****************/
737
738  typedef UGraphExtender<UndirGraphExtender<ListGraphBase> >
739  ExtendedListUGraphBase;
740
741  /// \addtogroup graphs
742  /// @{
743
744  ///An undirected list graph class.
745
[2117]746  ///This is a simple and fast undirected graph implementation.
[2116]747  ///
748  ///It conforms to the
[2117]749  ///\ref concept::UGraph "UGraph concept".
[2116]750  ///
751  ///\sa concept::UGraph.
752  ///
753  class ListUGraph : public ExtendedListUGraphBase {
[2128]754  private:
755    ///ListUGraph is \e not copy constructible. Use UGraphCopy() instead.
756
757    ///ListUGraph is \e not copy constructible. Use UGraphCopy() instead.
758    ///
759    ListUGraph(const ListUGraph &) :ExtendedListUGraphBase()  {};
[2132]760    ///\brief Assignment of ListUGraph to another one is \e not allowed.
[2128]761    ///Use UGraphCopy() instead.
762
[2132]763    ///Assignment of ListUGraph to another one is \e not allowed.
[2128]764    ///Use UGraphCopy() instead.
765    void operator=(const ListUGraph &) {}
[2116]766  public:
[2128]767    /// Constructor
768   
769    /// Constructor.
770    ///
771    ListUGraph() {}
772
[2116]773    typedef ExtendedListUGraphBase Parent;
774    /// \brief Add a new node to the graph.
775    ///
776    /// \return the new node.
777    ///
778    Node addNode() { return Parent::addNode(); }
779
780    /// \brief Add a new edge to the graph.
781    ///
782    /// Add a new edge to the graph with source node \c s
783    /// and target node \c t.
784    /// \return the new undirected edge.
785    UEdge addEdge(const Node& s, const Node& t) {
786      return Parent::addEdge(s, t);
787    }
[2160]788    /// \brief Changes the source of \c e to \c n
789    ///
790    /// Changes the source of \c e to \c n
791    ///
792    ///\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s
793    ///referencing the changed edge remain
794    ///valid. However <tt>OutEdgeIt</tt>s are invalidated.
795    void changeSource(UEdge e, Node n) {
796      Parent::changeSource(e,n);
797    }   
[2116]798    /// \brief Changes the target of \c e to \c n
799    ///
800    /// Changes the target of \c e to \c n
801    ///
[2160]802    /// \note The <tt>EdgeIt</tt>s referencing the changed edge remain
803    /// valid. However the other iterators may be invalidated.
[2116]804    void changeTarget(UEdge e, Node n) {
805      Parent::changeTarget(e,n);
806    }
[2160]807    /// \brief Changes the source of \c e to \c n
[2116]808    ///
[2160]809    /// Changes the source of \c e to \c n. It changes the proper
810    /// node of the represented undirected edge.
[2116]811    ///
[2160]812    ///\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s
[2116]813    ///referencing the changed edge remain
[2160]814    ///valid. However <tt>OutEdgeIt</tt>s are invalidated.
815    void changeSource(Edge e, Node n) {
816      if (Parent::direction(e)) {
817        Parent::changeSource(e,n);
818      } else {
819        Parent::changeTarget(e,n);
820      }
821    }
822    /// \brief Changes the target of \c e to \c n
823    ///
824    /// Changes the target of \c e to \c n. It changes the proper
825    /// node of the represented undirected edge.
826    ///
827    ///\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s
828    ///referencing the changed edge remain
829    ///valid. However <tt>InEdgeIt</tt>s are invalidated.
830    void changeTarget(Edge e, Node n) {
831      if (Parent::direction(e)) {
832        Parent::changeTarget(e,n);
833      } else {
834        Parent::changeSource(e,n);
835      }
[2116]836    }
837    /// \brief Contract two nodes.
838    ///
839    /// This function contracts two nodes.
840    ///
841    /// Node \p b will be removed but instead of deleting
842    /// its neighboring edges, they will be joined to \p a.
843    /// The last parameter \p r controls whether to remove loops. \c true
844    /// means that loops will be removed.
845    ///
[2160]846    /// \note The <tt>EdgeIt</tt>s referencing a moved edge remain
[2116]847    /// valid.
848    void contract(Node a, Node b, bool r = true) {
849      for(IncEdgeIt e(*this, b); e!=INVALID;) {
850        IncEdgeIt f = e; ++f;
851        if (r && runningNode(e) == a) {
852          erase(e);
853        } else if (source(e) == b) {
854          changeSource(e, a);
855        } else {
856          changeTarget(e, a);
857        }
858        e = f;
859      }
860      erase(b);
861    }
862  };
863
864
865  class ListBpUGraphBase {
866  public:
867
868    class NodeSetError : public LogicError {
[2160]869    public:
[2151]870      virtual const char* what() const throw() {
[2116]871        return "lemon::ListBpUGraph::NodeSetError";
872      }
873    };
874
875  protected:
876
877    struct NodeT {
878      int first_edge, prev, next;
879    };
880
881    struct UEdgeT {
882      int aNode, prev_out, next_out;
883      int bNode, prev_in, next_in;
884    };
885
886    std::vector<NodeT> aNodes;
887    std::vector<NodeT> bNodes;
888
889    std::vector<UEdgeT> edges;
890
891    int first_anode;
892    int first_free_anode;
893
894    int first_bnode;
895    int first_free_bnode;
896
897    int first_free_edge;
898
899  public:
900 
901    class Node {
902      friend class ListBpUGraphBase;
903    protected:
904      int id;
905
906      explicit Node(int _id) : id(_id) {}
907    public:
908      Node() {}
909      Node(Invalid) { id = -1; }
910      bool operator==(const Node i) const {return id==i.id;}
911      bool operator!=(const Node i) const {return id!=i.id;}
912      bool operator<(const Node i) const {return id<i.id;}
913    };
914
915    class UEdge {
916      friend class ListBpUGraphBase;
917    protected:
918      int id;
919
920      explicit UEdge(int _id) { id = _id;}
921    public:
922      UEdge() {}
923      UEdge (Invalid) { id = -1; }
924      bool operator==(const UEdge i) const {return id==i.id;}
925      bool operator!=(const UEdge i) const {return id!=i.id;}
926      bool operator<(const UEdge i) const {return id<i.id;}
927    };
928
929    ListBpUGraphBase()
930      : first_anode(-1), first_free_anode(-1),
931        first_bnode(-1), first_free_bnode(-1),
932        first_free_edge(-1) {}
933
934    void firstANode(Node& node) const {
935      node.id = first_anode != -1 ? (first_anode << 1) : -1;
936    }
937    void nextANode(Node& node) const {
938      node.id = aNodes[node.id >> 1].next;
939    }
940
941    void firstBNode(Node& node) const {
942      node.id = first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
943    }
944    void nextBNode(Node& node) const {
945      node.id = bNodes[node.id >> 1].next;
946    }
947
948    void first(Node& node) const {
949      if (first_anode != -1) {
950        node.id = (first_anode << 1);
951      } else if (first_bnode != -1) {
952        node.id = (first_bnode << 1) + 1;
953      } else {
954        node.id = -1;
955      }
956    }
957    void next(Node& node) const {
958      if (aNode(node)) {
959        node.id = aNodes[node.id >> 1].next;
960        if (node.id == -1) {
961          if (first_bnode != -1) {
962            node.id = (first_bnode << 1) + 1;
963          }
964        }
965      } else {
966        node.id = bNodes[node.id >> 1].next;
967      }
968    }
969 
970    void first(UEdge& edge) const {
971      int aNodeId = first_anode;
972      while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
973        aNodeId = aNodes[aNodeId].next != -1 ?
974          aNodes[aNodeId].next >> 1 : -1;
975      }
976      if (aNodeId != -1) {
977        edge.id = aNodes[aNodeId].first_edge;
978      } else {
979        edge.id = -1;
980      }
981    }
982    void next(UEdge& edge) const {
983      int aNodeId = edges[edge.id].aNode >> 1;
984      edge.id = edges[edge.id].next_out;
985      if (edge.id == -1) {
986        aNodeId = aNodes[aNodeId].next != -1 ?
987          aNodes[aNodeId].next >> 1 : -1;
988        while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
989          aNodeId = aNodes[aNodeId].next != -1 ?
990          aNodes[aNodeId].next >> 1 : -1;
991        }
992        if (aNodeId != -1) {
993          edge.id = aNodes[aNodeId].first_edge;
994        } else {
995          edge.id = -1;
996        }
997      }
998    }
999
1000    void firstFromANode(UEdge& edge, const Node& node) const {
1001      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
1002      edge.id = aNodes[node.id >> 1].first_edge;
1003    }
1004    void nextFromANode(UEdge& edge) const {
1005      edge.id = edges[edge.id].next_out;
1006    }
1007
1008    void firstFromBNode(UEdge& edge, const Node& node) const {
1009      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
1010      edge.id = bNodes[node.id >> 1].first_edge;
1011    }
1012    void nextFromBNode(UEdge& edge) const {
1013      edge.id = edges[edge.id].next_in;
1014    }
1015
1016    static int id(const Node& node) {
1017      return node.id;
1018    }
1019    static Node nodeFromId(int id) {
1020      return Node(id);
1021    }
1022    int maxNodeId() const {
1023      return aNodes.size() > bNodes.size() ?
1024        aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
1025    }
1026 
1027    static int id(const UEdge& edge) {
1028      return edge.id;
1029    }
1030    static UEdge uEdgeFromId(int id) {
1031      return UEdge(id);
1032    }
1033    int maxUEdgeId() const {
1034      return edges.size();
1035    }
1036 
1037    static int aNodeId(const Node& node) {
1038      return node.id >> 1;
1039    }
1040    static Node fromANodeId(int id) {
1041      return Node(id << 1);
1042    }
1043    int maxANodeId() const {
1044      return aNodes.size();
1045    }
1046
1047    static int bNodeId(const Node& node) {
1048      return node.id >> 1;
1049    }
1050    static Node fromBNodeId(int id) {
1051      return Node((id << 1) + 1);
1052    }
1053    int maxBNodeId() const {
1054      return bNodes.size();
1055    }
1056
1057    Node aNode(const UEdge& edge) const {
1058      return Node(edges[edge.id].aNode);
1059    }
1060    Node bNode(const UEdge& edge) const {
1061      return Node(edges[edge.id].bNode);
1062    }
1063
1064    static bool aNode(const Node& node) {
1065      return (node.id & 1) == 0;
1066    }
1067
1068    static bool bNode(const Node& node) {
1069      return (node.id & 1) == 1;
1070    }
1071
1072    Node addANode() {
1073      int aNodeId;
1074      if (first_free_anode == -1) {
1075        aNodeId = aNodes.size();
1076        aNodes.push_back(NodeT());
1077      } else {
1078        aNodeId = first_free_anode;
1079        first_free_anode = aNodes[first_free_anode].next;
1080      }
1081      if (first_anode != -1) {
1082        aNodes[aNodeId].next = first_anode << 1;
1083        aNodes[first_anode].prev = aNodeId << 1;
1084      } else {
1085        aNodes[aNodeId].next = -1;
1086      }
1087      aNodes[aNodeId].prev = -1;
1088      first_anode = aNodeId;
1089      aNodes[aNodeId].first_edge = -1;
1090      return Node(aNodeId << 1);
1091    }
1092
1093    Node addBNode() {
1094      int bNodeId;
1095      if (first_free_bnode == -1) {
1096        bNodeId = bNodes.size();
1097        bNodes.push_back(NodeT());
1098      } else {
1099        bNodeId = first_free_bnode;
1100        first_free_bnode = bNodes[first_free_bnode].next;
1101      }
1102      if (first_bnode != -1) {
1103        bNodes[bNodeId].next = (first_bnode << 1) + 1;
1104        bNodes[first_bnode].prev = (bNodeId << 1) + 1;
1105      } else {
1106        bNodes[bNodeId].next = -1;
1107      }
1108      first_bnode = bNodeId;
1109      bNodes[bNodeId].first_edge = -1;
1110      return Node((bNodeId << 1) + 1);
1111    }
1112
1113    UEdge addEdge(const Node& source, const Node& target) {
1114      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
1115      int edgeId;
1116      if (first_free_edge != -1) {
1117        edgeId = first_free_edge;
1118        first_free_edge = edges[edgeId].next_out;
1119      } else {
1120        edgeId = edges.size();
1121        edges.push_back(UEdgeT());
1122      }
1123      if ((source.id & 1) == 0) {
1124        edges[edgeId].aNode = source.id;
1125        edges[edgeId].bNode = target.id;
1126      } else {
1127        edges[edgeId].aNode = target.id;
1128        edges[edgeId].bNode = source.id;
1129      }
1130      edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
1131      edges[edgeId].prev_out = -1;
1132      if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
1133        edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
1134      }
1135      aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
1136      edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
1137      edges[edgeId].prev_in = -1;
1138      if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
1139        edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
1140      }
1141      bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
1142      return UEdge(edgeId);
1143    }
1144
1145    void erase(const Node& node) {
1146      if (aNode(node)) {
1147        int aNodeId = node.id >> 1;
1148        if (aNodes[aNodeId].prev != -1) {
1149          aNodes[aNodes[aNodeId].prev >> 1].next = aNodes[aNodeId].next;
1150        } else {
1151          first_anode = aNodes[aNodeId].next >> 1;
1152        }
1153        if (aNodes[aNodeId].next != -1) {
1154          aNodes[aNodes[aNodeId].next >> 1].prev = aNodes[aNodeId].prev;
1155        }
1156        aNodes[aNodeId].next = first_free_anode;
1157        first_free_anode = aNodeId;
1158      } else {
1159        int bNodeId = node.id >> 1;
1160        if (bNodes[bNodeId].prev != -1) {
1161          bNodes[bNodes[bNodeId].prev >> 1].next = bNodes[bNodeId].next;
1162        } else {
1163          first_bnode = bNodes[bNodeId].next >> 1;
1164        }
1165        if (bNodes[bNodeId].next != -1) {
1166          bNodes[bNodes[bNodeId].next >> 1].prev = bNodes[bNodeId].prev;
1167        }
1168        bNodes[bNodeId].next = first_free_bnode;
1169        first_free_bnode = bNodeId;
1170      }
1171    }
1172
1173    void erase(const UEdge& edge) {
1174
1175      if (edges[edge.id].prev_out != -1) {
1176        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
1177      } else {
1178        aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;
1179      }
1180      if (edges[edge.id].next_out != -1) {
1181        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
1182      }
1183
1184      if (edges[edge.id].prev_in != -1) {
1185        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
1186      } else {
1187        bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;
1188      }
1189      if (edges[edge.id].next_in != -1) {
1190        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
1191      }
1192
1193      edges[edge.id].next_out = first_free_edge;
1194      first_free_edge = edge.id;
1195    }
[2128]1196 
[2116]1197    void clear() {
1198      aNodes.clear();
1199      bNodes.clear();
1200      edges.clear();
1201      first_anode = -1;
1202      first_free_anode = -1;
1203      first_bnode = -1;
1204      first_free_bnode = -1;
1205      first_free_edge = -1;
1206    }
1207
[2160]1208    void changeANode(const UEdge& edge, const Node& node) {
1209      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
1210      if (edges[edge.id].prev_out != -1) {
1211        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
1212      } else {
1213        aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;
1214      }
1215      if (edges[edge.id].next_out != -1) {
1216        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out; 
1217      }
1218      if (aNodes[node.id >> 1].first_edge != -1) {
1219        edges[aNodes[node.id >> 1].first_edge].prev_out = edge.id;
1220      }
1221      edges[edge.id].prev_out = -1;
1222      edges[edge.id].next_out = aNodes[node.id >> 1].first_edge;
1223      aNodes[node.id >> 1].first_edge = edge.id;
1224      edges[edge.id].aNode = node.id;
1225    }
1226
1227    void changeBNode(const UEdge& edge, const Node& node) {
1228      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
1229      if (edges[edge.id].prev_in != -1) {
1230        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
1231      } else {
1232        bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;
1233      }
1234      if (edges[edge.id].next_in != -1) {
1235        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in; 
1236      }
1237      if (bNodes[node.id >> 1].first_edge != -1) {
1238        edges[bNodes[node.id >> 1].first_edge].prev_in = edge.id;
1239      }
1240      edges[edge.id].prev_in = -1;
1241      edges[edge.id].next_in = bNodes[node.id >> 1].first_edge;
1242      bNodes[node.id >> 1].first_edge = edge.id;
1243      edges[edge.id].bNode = node.id;
1244    }
1245
[2116]1246  };
1247
1248
1249  typedef BpUGraphExtender< ListBpUGraphBase > ExtendedListBpUGraphBase;
1250
1251  /// \ingroup graphs
1252  ///
1253  /// \brief A smart bipartite undirected graph class.
1254  ///
1255  /// This is a bipartite undirected graph implementation.
[2117]1256  /// It is conforms to the \ref concept::BpUGraph "BpUGraph concept".
[2116]1257  /// \sa concept::BpUGraph.
1258  ///
[2160]1259  class ListBpUGraph : public ExtendedListBpUGraphBase {
1260    /// \brief ListBpUGraph is \e not copy constructible.
1261    ///
1262    ///ListBpUGraph is \e not copy constructible.
1263    ListBpUGraph(const ListBpUGraph &) :ExtendedListBpUGraphBase()  {};
1264    /// \brief Assignment of ListBpUGraph to another one is \e not
1265    /// allowed.
1266    ///
1267    /// Assignment of ListBpUGraph to another one is \e not allowed.
1268    void operator=(const ListBpUGraph &) {}
1269  public:
1270    /// \brief Constructor
1271    ///   
1272    /// Constructor.
1273    ///
1274    ListBpUGraph() {}
1275
1276    typedef ExtendedListBpUGraphBase Parent;
1277    /// \brief Add a new ANode to the graph.
1278    ///
1279    /// \return the new node.
1280    ///
1281    Node addANode() { return Parent::addANode(); }
1282
1283    /// \brief Add a new BNode to the graph.
1284    ///
1285    /// \return the new node.
1286    ///
1287    Node addBNode() { return Parent::addBNode(); }
1288
1289    /// \brief Add a new edge to the graph.
1290    ///
1291    /// Add a new edge to the graph with an ANode and a BNode.
1292    /// \return the new undirected edge.
1293    UEdge addEdge(const Node& s, const Node& t) {
1294      return Parent::addEdge(s, t);
1295    }
1296
1297    /// \brief Changes the ANode of \c e to \c n
1298    ///
1299    /// Changes the ANode of \c e to \c n
1300    ///
1301    ///\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s referencing
1302    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are
1303    ///invalidated.
1304    void changeANode(UEdge e, Node n) {
1305      Parent::changeANode(e,n);
1306    }
1307
1308    /// \brief Changes the BNode of \c e to \c n
1309    ///
1310    /// Changes the BNode of \c e to \c n
1311    ///
1312    /// \note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s
1313    /// referencing the changed edge remain
1314    /// valid. However <tt>InEdgeIt</tt>s are invalidated.
1315    void changeBNode(UEdge e, Node n) {
1316      Parent::changeBNode(e,n);
1317    }
1318
1319    /// \brief Changes the source(ANode) of \c e to \c n
1320    ///
1321    /// Changes the source(ANode) of \c e to \c n
1322    ///
1323    ///\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s referencing
1324    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are
1325    ///invalidated.
1326    void changeSource(UEdge e, Node n) {
1327      Parent::changeANode(e,n);
1328    }
1329
1330    /// \brief Changes the target(BNode) of \c e to \c n
1331    ///
1332    /// Changes the target(BNode) of \c e to \c n
1333    ///
1334    /// \note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s
1335    /// referencing the changed edge remain
1336    /// valid. However <tt>InEdgeIt</tt>s are invalidated.
1337    void changeTarget(UEdge e, Node n) {
1338      Parent::changeBNode(e,n);
1339    }
1340
1341    /// \brief Changes the source of \c e to \c n
1342    ///
1343    /// Changes the source of \c e to \c n. It changes the proper
1344    /// node of the represented undirected edge.
1345    ///
1346    ///\note The <tt>EdgeIt</tt>s and <tt>InEdgeIt</tt>s
1347    ///referencing the changed edge remain
1348    ///valid. However <tt>OutEdgeIt</tt>s are invalidated.
1349    void changeSource(Edge e, Node n) {
1350      if (Parent::direction(e)) {
1351        Parent::changeANode(e,n);
1352      } else {
1353        Parent::changeBNode(e,n);
1354      }
1355    }
1356    /// \brief Changes the target of \c e to \c n
1357    ///
1358    /// Changes the target of \c e to \c n. It changes the proper
1359    /// node of the represented undirected edge.
1360    ///
1361    ///\note The <tt>EdgeIt</tt>s and <tt>OutEdgeIt</tt>s
1362    ///referencing the changed edge remain
1363    ///valid. However <tt>InEdgeIt</tt>s are invalidated.
1364    void changeTarget(Edge e, Node n) {
1365      if (Parent::direction(e)) {
1366        Parent::changeBNode(e,n);
1367      } else {
1368        Parent::changeANode(e,n);
1369      }
1370    }
1371    /// \brief Contract two nodes.
1372    ///
1373    /// This function contracts two nodes.
1374    ///
1375    /// Node \p b will be removed but instead of deleting its
1376    /// neighboring edges, they will be joined to \p a.  The two nodes
1377    /// should be from the same nodeset, of course.
1378    ///
1379    /// \note The <tt>EdgeIt</tt>s referencing a moved edge remain
1380    /// valid.
1381    void contract(const Node& a, const Node& b) {
1382      LEMON_ASSERT(Parent::aNode(a) == Parent::aNode(b), NodeSetError());
1383      if (Parent::aNode(a)) {
1384        for (IncEdgeIt e(*this, b); e!=INVALID;) {
1385          IncEdgeIt f = e; ++f;
1386          changeSource(e, a);
1387          e = f;
1388        }
1389      } else {
1390        for (IncEdgeIt e(*this, b); e!=INVALID;) {
1391          IncEdgeIt f = e; ++f;
1392          changeTarget(e, a);
1393          e = f;
1394        }
1395      }
1396      erase(b);
1397    }
1398
1399  };
[2116]1400
1401 
1402  /// @} 
[948]1403} //namespace lemon
[946]1404 
[400]1405
[946]1406#endif
Note: See TracBrowser for help on using the repository browser.