alpar@209: /* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@39:  *
alpar@209:  * This file is a part of LEMON, a generic C++ optimization library.
alpar@39:  *
alpar@39:  * Copyright (C) 2003-2008
alpar@39:  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@39:  * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@39:  *
alpar@39:  * Permission to use, modify and distribute this software is granted
alpar@39:  * provided that this copyright notice appears in all copies. For
alpar@39:  * precise terms see the accompanying LICENSE file.
alpar@39:  *
alpar@39:  * This software is provided "AS IS" with no warranty of any kind,
alpar@39:  * express or implied, and with no claim as to its suitability for any
alpar@39:  * purpose.
alpar@39:  *
alpar@39:  */
alpar@39: 
deba@57: #ifndef LEMON_LIST_GRAPH_H
deba@57: #define LEMON_LIST_GRAPH_H
deba@57: 
deba@57: ///\ingroup graphs
deba@57: ///\file
deba@57: ///\brief ListDigraph, ListGraph classes.
deba@57: 
deba@220: #include <lemon/core.h>
deba@220: #include <lemon/error.h>
deba@57: #include <lemon/bits/graph_extender.h>
deba@57: 
deba@57: #include <vector>
deba@57: #include <list>
deba@57: 
deba@57: namespace lemon {
deba@57: 
deba@57:   class ListDigraphBase {
deba@57: 
deba@57:   protected:
deba@57:     struct NodeT {
deba@57:       int first_in, first_out;
deba@57:       int prev, next;
deba@57:     };
alpar@209: 
deba@57:     struct ArcT {
deba@57:       int target, source;
deba@57:       int prev_in, prev_out;
deba@57:       int next_in, next_out;
deba@57:     };
deba@57: 
deba@57:     std::vector<NodeT> nodes;
deba@57: 
deba@57:     int first_node;
deba@57: 
deba@57:     int first_free_node;
deba@57: 
deba@57:     std::vector<ArcT> arcs;
deba@57: 
deba@57:     int first_free_arc;
alpar@209: 
deba@57:   public:
alpar@209: 
deba@57:     typedef ListDigraphBase Digraph;
alpar@209: 
deba@57:     class Node {
deba@57:       friend class ListDigraphBase;
deba@57:     protected:
deba@57: 
deba@57:       int id;
deba@57:       explicit Node(int pid) { id = pid;}
deba@57: 
deba@57:     public:
deba@57:       Node() {}
deba@57:       Node (Invalid) { id = -1; }
deba@57:       bool operator==(const Node& node) const {return id == node.id;}
deba@57:       bool operator!=(const Node& node) const {return id != node.id;}
deba@57:       bool operator<(const Node& node) const {return id < node.id;}
deba@57:     };
deba@57: 
deba@57:     class Arc {
deba@57:       friend class ListDigraphBase;
deba@57:     protected:
deba@57: 
deba@57:       int id;
deba@57:       explicit Arc(int pid) { id = pid;}
deba@57: 
deba@57:     public:
deba@57:       Arc() {}
deba@57:       Arc (Invalid) { id = -1; }
deba@57:       bool operator==(const Arc& arc) const {return id == arc.id;}
deba@57:       bool operator!=(const Arc& arc) const {return id != arc.id;}
deba@57:       bool operator<(const Arc& arc) const {return id < arc.id;}
deba@57:     };
deba@57: 
deba@57: 
deba@57: 
deba@57:     ListDigraphBase()
deba@57:       : nodes(), first_node(-1),
alpar@209:         first_free_node(-1), arcs(), first_free_arc(-1) {}
deba@57: 
alpar@209: 
alpar@209:     int maxNodeId() const { return nodes.size()-1; }
deba@57:     int maxArcId() const { return arcs.size()-1; }
deba@57: 
deba@57:     Node source(Arc e) const { return Node(arcs[e.id].source); }
deba@57:     Node target(Arc e) const { return Node(arcs[e.id].target); }
deba@57: 
deba@57: 
alpar@209:     void first(Node& node) const {
deba@57:       node.id = first_node;
deba@57:     }
deba@57: 
deba@57:     void next(Node& node) const {
deba@57:       node.id = nodes[node.id].next;
deba@57:     }
deba@57: 
deba@57: 
alpar@209:     void first(Arc& arc) const {
deba@57:       int n;
alpar@209:       for(n = first_node;
alpar@209:           n!=-1 && nodes[n].first_in == -1;
alpar@209:           n = nodes[n].next) {}
kpeter@73:       arc.id = (n == -1) ? -1 : nodes[n].first_in;
deba@57:     }
deba@57: 
deba@57:     void next(Arc& arc) const {
deba@57:       if (arcs[arc.id].next_in != -1) {
alpar@209:         arc.id = arcs[arc.id].next_in;
deba@57:       } else {
alpar@209:         int n;
alpar@209:         for(n = nodes[arcs[arc.id].target].next;
alpar@209:             n!=-1 && nodes[n].first_in == -1;
alpar@209:             n = nodes[n].next) {}
alpar@209:         arc.id = (n == -1) ? -1 : nodes[n].first_in;
alpar@209:       }
deba@57:     }
deba@57: 
deba@57:     void firstOut(Arc &e, const Node& v) const {
deba@57:       e.id = nodes[v.id].first_out;
deba@57:     }
deba@57:     void nextOut(Arc &e) const {
deba@57:       e.id=arcs[e.id].next_out;
deba@57:     }
deba@57: 
deba@57:     void firstIn(Arc &e, const Node& v) const {
deba@57:       e.id = nodes[v.id].first_in;
deba@57:     }
deba@57:     void nextIn(Arc &e) const {
deba@57:       e.id=arcs[e.id].next_in;
deba@57:     }
deba@57: 
alpar@209: 
deba@57:     static int id(Node v) { return v.id; }
deba@57:     static int id(Arc e) { return e.id; }
deba@57: 
deba@57:     static Node nodeFromId(int id) { return Node(id);}
deba@57:     static Arc arcFromId(int id) { return Arc(id);}
deba@57: 
alpar@209:     bool valid(Node n) const {
alpar@209:       return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
alpar@209:         nodes[n.id].prev != -2;
deba@149:     }
deba@149: 
alpar@209:     bool valid(Arc a) const {
alpar@209:       return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
alpar@209:         arcs[a.id].prev_in != -2;
deba@149:     }
deba@149: 
alpar@209:     Node addNode() {
deba@57:       int n;
alpar@209: 
deba@57:       if(first_free_node==-1) {
alpar@209:         n = nodes.size();
alpar@209:         nodes.push_back(NodeT());
deba@57:       } else {
alpar@209:         n = first_free_node;
alpar@209:         first_free_node = nodes[n].next;
deba@57:       }
alpar@209: 
deba@57:       nodes[n].next = first_node;
deba@57:       if(first_node != -1) nodes[first_node].prev = n;
deba@57:       first_node = n;
deba@57:       nodes[n].prev = -1;
alpar@209: 
deba@57:       nodes[n].first_in = nodes[n].first_out = -1;
alpar@209: 
deba@57:       return Node(n);
deba@57:     }
alpar@209: 
deba@57:     Arc addArc(Node u, Node v) {
alpar@209:       int n;
deba@57: 
deba@57:       if (first_free_arc == -1) {
alpar@209:         n = arcs.size();
alpar@209:         arcs.push_back(ArcT());
deba@57:       } else {
alpar@209:         n = first_free_arc;
alpar@209:         first_free_arc = arcs[n].next_in;
deba@57:       }
alpar@209: 
alpar@209:       arcs[n].source = u.id;
deba@57:       arcs[n].target = v.id;
deba@57: 
deba@57:       arcs[n].next_out = nodes[u.id].first_out;
deba@57:       if(nodes[u.id].first_out != -1) {
alpar@209:         arcs[nodes[u.id].first_out].prev_out = n;
deba@57:       }
alpar@209: 
deba@57:       arcs[n].next_in = nodes[v.id].first_in;
deba@57:       if(nodes[v.id].first_in != -1) {
alpar@209:         arcs[nodes[v.id].first_in].prev_in = n;
deba@57:       }
alpar@209: 
deba@57:       arcs[n].prev_in = arcs[n].prev_out = -1;
alpar@209: 
deba@57:       nodes[u.id].first_out = nodes[v.id].first_in = n;
deba@57: 
deba@57:       return Arc(n);
deba@57:     }
alpar@209: 
deba@57:     void erase(const Node& node) {
deba@57:       int n = node.id;
alpar@209: 
deba@57:       if(nodes[n].next != -1) {
alpar@209:         nodes[nodes[n].next].prev = nodes[n].prev;
deba@57:       }
alpar@209: 
deba@57:       if(nodes[n].prev != -1) {
alpar@209:         nodes[nodes[n].prev].next = nodes[n].next;
deba@57:       } else {
alpar@209:         first_node = nodes[n].next;
deba@57:       }
alpar@209: 
deba@57:       nodes[n].next = first_free_node;
deba@57:       first_free_node = n;
deba@149:       nodes[n].prev = -2;
deba@57: 
deba@57:     }
alpar@209: 
deba@57:     void erase(const Arc& arc) {
deba@57:       int n = arc.id;
alpar@209: 
deba@57:       if(arcs[n].next_in!=-1) {
alpar@209:         arcs[arcs[n].next_in].prev_in = arcs[n].prev_in;
deba@57:       }
deba@57: 
deba@57:       if(arcs[n].prev_in!=-1) {
alpar@209:         arcs[arcs[n].prev_in].next_in = arcs[n].next_in;
deba@57:       } else {
alpar@209:         nodes[arcs[n].target].first_in = arcs[n].next_in;
deba@57:       }
deba@57: 
alpar@209: 
deba@57:       if(arcs[n].next_out!=-1) {
alpar@209:         arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
alpar@209:       }
deba@57: 
deba@57:       if(arcs[n].prev_out!=-1) {
alpar@209:         arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
deba@57:       } else {
alpar@209:         nodes[arcs[n].source].first_out = arcs[n].next_out;
deba@57:       }
alpar@209: 
deba@57:       arcs[n].next_in = first_free_arc;
deba@149:       first_free_arc = n;
deba@149:       arcs[n].prev_in = -2;
deba@57:     }
deba@57: 
deba@57:     void clear() {
deba@57:       arcs.clear();
deba@57:       nodes.clear();
deba@57:       first_node = first_free_node = first_free_arc = -1;
deba@57:     }
deba@57: 
deba@57:   protected:
alpar@209:     void changeTarget(Arc e, Node n)
deba@57:     {
deba@57:       if(arcs[e.id].next_in != -1)
alpar@209:         arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in;
deba@57:       if(arcs[e.id].prev_in != -1)
alpar@209:         arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in;
deba@57:       else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in;
deba@57:       if (nodes[n.id].first_in != -1) {
alpar@209:         arcs[nodes[n.id].first_in].prev_in = e.id;
deba@57:       }
deba@57:       arcs[e.id].target = n.id;
deba@57:       arcs[e.id].prev_in = -1;
deba@57:       arcs[e.id].next_in = nodes[n.id].first_in;
deba@57:       nodes[n.id].first_in = e.id;
deba@57:     }
alpar@209:     void changeSource(Arc e, Node n)
deba@57:     {
deba@57:       if(arcs[e.id].next_out != -1)
alpar@209:         arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out;
deba@57:       if(arcs[e.id].prev_out != -1)
alpar@209:         arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out;
deba@57:       else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out;
deba@57:       if (nodes[n.id].first_out != -1) {
alpar@209:         arcs[nodes[n.id].first_out].prev_out = e.id;
deba@57:       }
deba@57:       arcs[e.id].source = n.id;
deba@57:       arcs[e.id].prev_out = -1;
deba@57:       arcs[e.id].next_out = nodes[n.id].first_out;
deba@57:       nodes[n.id].first_out = e.id;
deba@57:     }
deba@57: 
deba@57:   };
deba@57: 
deba@57:   typedef DigraphExtender<ListDigraphBase> ExtendedListDigraphBase;
deba@57: 
kpeter@73:   /// \addtogroup graphs
deba@57:   /// @{
deba@57: 
alpar@209:   ///A general directed graph structure.
deba@57: 
alpar@209:   ///\ref ListDigraph is a simple and fast <em>directed graph</em>
alpar@209:   ///implementation based on static linked lists that are stored in
alpar@209:   ///\c std::vector structures.
deba@57:   ///
deba@57:   ///It conforms to the \ref concepts::Digraph "Digraph concept" and it
kpeter@73:   ///also provides several useful additional functionalities.
kpeter@73:   ///Most of the member functions and nested classes are documented
kpeter@73:   ///only in the concept class.
deba@57:   ///
deba@57:   ///An important extra feature of this digraph implementation is that
deba@57:   ///its maps are real \ref concepts::ReferenceMap "reference map"s.
deba@57:   ///
kpeter@73:   ///\sa concepts::Digraph
deba@57: 
deba@57:   class ListDigraph : public ExtendedListDigraphBase {
deba@57:   private:
kpeter@73:     ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
alpar@209: 
kpeter@73:     ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
deba@57:     ///
deba@57:     ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
deba@57:     ///\brief Assignment of ListDigraph to another one is \e not allowed.
kpeter@73:     ///Use copyDigraph() instead.
deba@57: 
deba@57:     ///Assignment of ListDigraph to another one is \e not allowed.
kpeter@73:     ///Use copyDigraph() instead.
deba@57:     void operator=(const ListDigraph &) {}
deba@57:   public:
deba@57: 
deba@57:     typedef ExtendedListDigraphBase Parent;
deba@57: 
deba@57:     /// Constructor
alpar@209: 
deba@57:     /// Constructor.
deba@57:     ///
deba@57:     ListDigraph() {}
deba@57: 
deba@57:     ///Add a new node to the digraph.
alpar@209: 
kpeter@73:     ///Add a new node to the digraph.
kpeter@73:     ///\return the new node.
deba@57:     Node addNode() { return Parent::addNode(); }
deba@57: 
deba@57:     ///Add a new arc to the digraph.
alpar@209: 
deba@57:     ///Add a new arc to the digraph with source node \c s
deba@57:     ///and target node \c t.
deba@57:     ///\return the new arc.
alpar@209:     Arc addArc(const Node& s, const Node& t) {
alpar@209:       return Parent::addArc(s, t);
deba@57:     }
deba@57: 
deba@234:     ///\brief Erase a node from the digraph.
deba@234:     ///
deba@234:     ///Erase a node from the digraph.
deba@234:     ///
deba@234:     void erase(const Node& n) { Parent::erase(n); }
deba@234: 
deba@234:     ///\brief Erase an arc from the digraph.
deba@234:     ///
deba@234:     ///Erase an arc from the digraph.
deba@234:     ///
deba@234:     void erase(const Arc& a) { Parent::erase(a); }
deba@234: 
deba@149:     /// Node validity check
deba@149: 
deba@149:     /// This function gives back true if the given node is valid,
alpar@209:     /// ie. it is a real node of the graph.
deba@149:     ///
deba@149:     /// \warning A Node pointing to a removed item
deba@149:     /// could become valid again later if new nodes are
deba@149:     /// added to the graph.
deba@149:     bool valid(Node n) const { return Parent::valid(n); }
deba@149: 
deba@149:     /// Arc validity check
deba@149: 
deba@149:     /// This function gives back true if the given arc is valid,
alpar@209:     /// ie. it is a real arc of the graph.
deba@149:     ///
deba@149:     /// \warning An Arc pointing to a removed item
deba@149:     /// could become valid again later if new nodes are
deba@149:     /// added to the graph.
deba@149:     bool valid(Arc a) const { return Parent::valid(a); }
deba@149: 
deba@235:     /// Change the target of \c a to \c n
deba@57: 
deba@235:     /// Change the target of \c a to \c n
deba@57:     ///
deba@57:     ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s referencing
deba@57:     ///the changed arc remain valid. However <tt>InArcIt</tt>s are
deba@57:     ///invalidated.
kpeter@73:     ///
deba@57:     ///\warning This functionality cannot be used together with the Snapshot
deba@57:     ///feature.
deba@235:     void changeTarget(Arc a, Node n) {
deba@235:       Parent::changeTarget(a,n);
deba@57:     }
deba@235:     /// Change the source of \c a to \c n
deba@57: 
deba@235:     /// Change the source of \c a to \c n
deba@57:     ///
deba@235:     ///\note The <tt>InArcIt</tt>s referencing the changed arc remain
kpeter@313:     ///valid. However the <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s are
deba@57:     ///invalidated.
kpeter@73:     ///
deba@57:     ///\warning This functionality cannot be used together with the Snapshot
deba@57:     ///feature.
deba@235:     void changeSource(Arc a, Node n) {
deba@235:       Parent::changeSource(a,n);
deba@57:     }
deba@57: 
deba@57:     /// Invert the direction of an arc.
deba@57: 
deba@57:     ///\note The <tt>ArcIt</tt>s referencing the changed arc remain
deba@57:     ///valid. However <tt>OutArcIt</tt>s and <tt>InArcIt</tt>s are
deba@57:     ///invalidated.
kpeter@73:     ///
deba@57:     ///\warning This functionality cannot be used together with the Snapshot
deba@57:     ///feature.
deba@57:     void reverseArc(Arc e) {
deba@57:       Node t=target(e);
deba@57:       changeTarget(e,source(e));
deba@57:       changeSource(e,t);
deba@57:     }
deba@57: 
kpeter@73:     /// Reserve memory for nodes.
kpeter@73: 
kpeter@73:     /// Using this function it is possible to avoid the superfluous memory
deba@57:     /// allocation: if you know that the digraph you want to build will
deba@57:     /// be very large (e.g. it will contain millions of nodes and/or arcs)
deba@57:     /// then it is worth reserving space for this amount before starting
deba@57:     /// to build the digraph.
deba@57:     /// \sa reserveArc
deba@57:     void reserveNode(int n) { nodes.reserve(n); };
deba@57: 
kpeter@73:     /// Reserve memory for arcs.
deba@57: 
kpeter@73:     /// Using this function it is possible to avoid the superfluous memory
deba@57:     /// allocation: if you know that the digraph you want to build will
deba@57:     /// be very large (e.g. it will contain millions of nodes and/or arcs)
deba@57:     /// then it is worth reserving space for this amount before starting
deba@57:     /// to build the digraph.
deba@57:     /// \sa reserveNode
deba@57:     void reserveArc(int m) { arcs.reserve(m); };
deba@57: 
deba@57:     ///Contract two nodes.
deba@57: 
deba@57:     ///This function contracts two nodes.
deba@57:     ///Node \p b will be removed but instead of deleting
deba@57:     ///incident arcs, they will be joined to \p a.
deba@57:     ///The last parameter \p r controls whether to remove loops. \c true
deba@57:     ///means that loops will be removed.
deba@57:     ///
kpeter@73:     ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
deba@57:     ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s
deba@57:     ///may be invalidated.
kpeter@73:     ///
deba@57:     ///\warning This functionality cannot be used together with the Snapshot
deba@57:     ///feature.
alpar@209:     void contract(Node a, Node b, bool r = true)
deba@57:     {
deba@57:       for(OutArcIt e(*this,b);e!=INVALID;) {
alpar@209:         OutArcIt f=e;
alpar@209:         ++f;
alpar@209:         if(r && target(e)==a) erase(e);
alpar@209:         else changeSource(e,a);
alpar@209:         e=f;
deba@57:       }
deba@57:       for(InArcIt e(*this,b);e!=INVALID;) {
alpar@209:         InArcIt f=e;
alpar@209:         ++f;
alpar@209:         if(r && source(e)==a) erase(e);
alpar@209:         else changeTarget(e,a);
alpar@209:         e=f;
deba@57:       }
deba@57:       erase(b);
deba@57:     }
deba@57: 
deba@57:     ///Split a node.
deba@57: 
deba@57:     ///This function splits a node. First a new node is added to the digraph,
deba@57:     ///then the source of each outgoing arc of \c n is moved to this new node.
deba@57:     ///If \c connect is \c true (this is the default value), then a new arc
deba@57:     ///from \c n to the newly created node is also added.
deba@57:     ///\return The newly created node.
deba@57:     ///
deba@57:     ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
deba@57:     ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s may
alpar@209:     ///be invalidated.
deba@57:     ///
alpar@280:     ///\warning This functionality cannot be used in conjunction with the
kpeter@73:     ///Snapshot feature.
deba@57:     Node split(Node n, bool connect = true) {
deba@57:       Node b = addNode();
deba@57:       for(OutArcIt e(*this,n);e!=INVALID;) {
kpeter@212:         OutArcIt f=e;
alpar@209:         ++f;
alpar@209:         changeSource(e,b);
alpar@209:         e=f;
deba@57:       }
deba@57:       if (connect) addArc(n,b);
deba@57:       return b;
deba@57:     }
alpar@209: 
deba@57:     ///Split an arc.
deba@57: 
deba@57:     ///This function splits an arc. First a new node \c b is added to
deba@57:     ///the digraph, then the original arc is re-targeted to \c
deba@57:     ///b. Finally an arc from \c b to the original target is added.
kpeter@73:     ///
kpeter@73:     ///\return The newly created node.
kpeter@73:     ///
kpeter@73:     ///\warning This functionality cannot be used together with the
kpeter@73:     ///Snapshot feature.
deba@57:     Node split(Arc e) {
deba@57:       Node b = addNode();
deba@57:       addArc(b,target(e));
deba@57:       changeTarget(e,b);
deba@57:       return b;
deba@57:     }
alpar@209: 
deba@57:     /// \brief Class to make a snapshot of the digraph and restore
kpeter@73:     /// it later.
deba@57:     ///
kpeter@73:     /// Class to make a snapshot of the digraph and restore it later.
deba@57:     ///
deba@57:     /// The newly added nodes and arcs can be removed using the
deba@57:     /// restore() function.
deba@57:     ///
kpeter@73:     /// \warning Arc and node deletions and other modifications (e.g.
alpar@209:     /// contracting, splitting, reversing arcs or nodes) cannot be
alpar@209:     /// restored. These events invalidate the snapshot.
deba@57:     class Snapshot {
deba@57:     protected:
deba@57: 
deba@57:       typedef Parent::NodeNotifier NodeNotifier;
deba@57: 
deba@57:       class NodeObserverProxy : public NodeNotifier::ObserverBase {
deba@57:       public:
deba@57: 
deba@57:         NodeObserverProxy(Snapshot& _snapshot)
deba@57:           : snapshot(_snapshot) {}
deba@57: 
deba@57:         using NodeNotifier::ObserverBase::attach;
deba@57:         using NodeNotifier::ObserverBase::detach;
deba@57:         using NodeNotifier::ObserverBase::attached;
alpar@209: 
deba@57:       protected:
alpar@209: 
deba@57:         virtual void add(const Node& node) {
deba@57:           snapshot.addNode(node);
deba@57:         }
deba@57:         virtual void add(const std::vector<Node>& nodes) {
deba@57:           for (int i = nodes.size() - 1; i >= 0; ++i) {
deba@57:             snapshot.addNode(nodes[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void erase(const Node& node) {
deba@57:           snapshot.eraseNode(node);
deba@57:         }
deba@57:         virtual void erase(const std::vector<Node>& nodes) {
deba@57:           for (int i = 0; i < int(nodes.size()); ++i) {
deba@57:             snapshot.eraseNode(nodes[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void build() {
deba@57:           Node node;
deba@57:           std::vector<Node> nodes;
alpar@209:           for (notifier()->first(node); node != INVALID;
deba@57:                notifier()->next(node)) {
deba@57:             nodes.push_back(node);
deba@57:           }
deba@57:           for (int i = nodes.size() - 1; i >= 0; --i) {
deba@57:             snapshot.addNode(nodes[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void clear() {
deba@57:           Node node;
alpar@209:           for (notifier()->first(node); node != INVALID;
deba@57:                notifier()->next(node)) {
deba@57:             snapshot.eraseNode(node);
deba@57:           }
deba@57:         }
deba@57: 
deba@57:         Snapshot& snapshot;
deba@57:       };
deba@57: 
deba@57:       class ArcObserverProxy : public ArcNotifier::ObserverBase {
deba@57:       public:
deba@57: 
deba@57:         ArcObserverProxy(Snapshot& _snapshot)
deba@57:           : snapshot(_snapshot) {}
deba@57: 
deba@57:         using ArcNotifier::ObserverBase::attach;
deba@57:         using ArcNotifier::ObserverBase::detach;
deba@57:         using ArcNotifier::ObserverBase::attached;
alpar@209: 
deba@57:       protected:
deba@57: 
deba@57:         virtual void add(const Arc& arc) {
deba@57:           snapshot.addArc(arc);
deba@57:         }
deba@57:         virtual void add(const std::vector<Arc>& arcs) {
deba@57:           for (int i = arcs.size() - 1; i >= 0; ++i) {
deba@57:             snapshot.addArc(arcs[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void erase(const Arc& arc) {
deba@57:           snapshot.eraseArc(arc);
deba@57:         }
deba@57:         virtual void erase(const std::vector<Arc>& arcs) {
deba@57:           for (int i = 0; i < int(arcs.size()); ++i) {
deba@57:             snapshot.eraseArc(arcs[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void build() {
deba@57:           Arc arc;
deba@57:           std::vector<Arc> arcs;
alpar@209:           for (notifier()->first(arc); arc != INVALID;
deba@57:                notifier()->next(arc)) {
deba@57:             arcs.push_back(arc);
deba@57:           }
deba@57:           for (int i = arcs.size() - 1; i >= 0; --i) {
deba@57:             snapshot.addArc(arcs[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void clear() {
deba@57:           Arc arc;
alpar@209:           for (notifier()->first(arc); arc != INVALID;
deba@57:                notifier()->next(arc)) {
deba@57:             snapshot.eraseArc(arc);
deba@57:           }
deba@57:         }
deba@57: 
deba@57:         Snapshot& snapshot;
deba@57:       };
alpar@209: 
deba@57:       ListDigraph *digraph;
deba@57: 
deba@57:       NodeObserverProxy node_observer_proxy;
deba@57:       ArcObserverProxy arc_observer_proxy;
deba@57: 
deba@57:       std::list<Node> added_nodes;
deba@57:       std::list<Arc> added_arcs;
deba@57: 
deba@57: 
deba@57:       void addNode(const Node& node) {
alpar@209:         added_nodes.push_front(node);
deba@57:       }
deba@57:       void eraseNode(const Node& node) {
alpar@209:         std::list<Node>::iterator it =
deba@57:           std::find(added_nodes.begin(), added_nodes.end(), node);
deba@57:         if (it == added_nodes.end()) {
deba@57:           clear();
deba@57:           arc_observer_proxy.detach();
deba@57:           throw NodeNotifier::ImmediateDetach();
deba@57:         } else {
deba@57:           added_nodes.erase(it);
deba@57:         }
deba@57:       }
deba@57: 
deba@57:       void addArc(const Arc& arc) {
alpar@209:         added_arcs.push_front(arc);
deba@57:       }
deba@57:       void eraseArc(const Arc& arc) {
alpar@209:         std::list<Arc>::iterator it =
deba@57:           std::find(added_arcs.begin(), added_arcs.end(), arc);
deba@57:         if (it == added_arcs.end()) {
deba@57:           clear();
alpar@209:           node_observer_proxy.detach();
deba@57:           throw ArcNotifier::ImmediateDetach();
deba@57:         } else {
deba@57:           added_arcs.erase(it);
alpar@209:         }
deba@57:       }
deba@57: 
deba@57:       void attach(ListDigraph &_digraph) {
alpar@209:         digraph = &_digraph;
alpar@209:         node_observer_proxy.attach(digraph->notifier(Node()));
deba@57:         arc_observer_proxy.attach(digraph->notifier(Arc()));
deba@57:       }
alpar@209: 
deba@57:       void detach() {
alpar@209:         node_observer_proxy.detach();
alpar@209:         arc_observer_proxy.detach();
deba@57:       }
deba@57: 
deba@57:       bool attached() const {
deba@57:         return node_observer_proxy.attached();
deba@57:       }
deba@57: 
deba@57:       void clear() {
deba@57:         added_nodes.clear();
alpar@209:         added_arcs.clear();
deba@57:       }
deba@57: 
deba@57:     public:
deba@57: 
deba@57:       /// \brief Default constructor.
deba@57:       ///
deba@57:       /// Default constructor.
deba@57:       /// To actually make a snapshot you must call save().
alpar@209:       Snapshot()
alpar@209:         : digraph(0), node_observer_proxy(*this),
deba@57:           arc_observer_proxy(*this) {}
alpar@209: 
deba@57:       /// \brief Constructor that immediately makes a snapshot.
alpar@209:       ///
deba@57:       /// This constructor immediately makes a snapshot of the digraph.
deba@57:       /// \param _digraph The digraph we make a snapshot of.
alpar@209:       Snapshot(ListDigraph &_digraph)
alpar@209:         : node_observer_proxy(*this),
deba@57:           arc_observer_proxy(*this) {
alpar@209:         attach(_digraph);
deba@57:       }
alpar@209: 
deba@57:       /// \brief Make a snapshot.
deba@57:       ///
deba@57:       /// Make a snapshot of the digraph.
deba@57:       ///
deba@57:       /// This function can be called more than once. In case of a repeated
deba@57:       /// call, the previous snapshot gets lost.
deba@57:       /// \param _digraph The digraph we make the snapshot of.
deba@57:       void save(ListDigraph &_digraph) {
deba@57:         if (attached()) {
deba@57:           detach();
deba@57:           clear();
deba@57:         }
deba@57:         attach(_digraph);
deba@57:       }
alpar@209: 
deba@57:       /// \brief Undo the changes until the last snapshot.
alpar@209:       //
deba@57:       /// Undo the changes until the last snapshot created by save().
deba@57:       void restore() {
alpar@209:         detach();
alpar@209:         for(std::list<Arc>::iterator it = added_arcs.begin();
deba@57:             it != added_arcs.end(); ++it) {
alpar@209:           digraph->erase(*it);
alpar@209:         }
alpar@209:         for(std::list<Node>::iterator it = added_nodes.begin();
deba@57:             it != added_nodes.end(); ++it) {
alpar@209:           digraph->erase(*it);
alpar@209:         }
deba@57:         clear();
deba@57:       }
deba@57: 
deba@57:       /// \brief Gives back true when the snapshot is valid.
deba@57:       ///
deba@57:       /// Gives back true when the snapshot is valid.
deba@57:       bool valid() const {
deba@57:         return attached();
deba@57:       }
deba@57:     };
alpar@209: 
deba@57:   };
deba@57: 
deba@57:   ///@}
deba@57: 
deba@57:   class ListGraphBase {
deba@57: 
deba@57:   protected:
deba@57: 
deba@57:     struct NodeT {
deba@57:       int first_out;
deba@57:       int prev, next;
deba@57:     };
alpar@209: 
deba@57:     struct ArcT {
deba@57:       int target;
deba@57:       int prev_out, next_out;
deba@57:     };
deba@57: 
deba@57:     std::vector<NodeT> nodes;
deba@57: 
deba@57:     int first_node;
deba@57: 
deba@57:     int first_free_node;
deba@57: 
deba@57:     std::vector<ArcT> arcs;
deba@57: 
deba@57:     int first_free_arc;
alpar@209: 
deba@57:   public:
alpar@209: 
deba@57:     typedef ListGraphBase Digraph;
deba@57: 
deba@57:     class Node;
deba@57:     class Arc;
deba@57:     class Edge;
alpar@209: 
deba@57:     class Node {
deba@57:       friend class ListGraphBase;
deba@57:     protected:
deba@57: 
deba@57:       int id;
deba@57:       explicit Node(int pid) { id = pid;}
deba@57: 
deba@57:     public:
deba@57:       Node() {}
deba@57:       Node (Invalid) { id = -1; }
deba@57:       bool operator==(const Node& node) const {return id == node.id;}
deba@57:       bool operator!=(const Node& node) const {return id != node.id;}
deba@57:       bool operator<(const Node& node) const {return id < node.id;}
deba@57:     };
deba@57: 
deba@57:     class Edge {
deba@57:       friend class ListGraphBase;
deba@57:     protected:
deba@57: 
deba@57:       int id;
deba@57:       explicit Edge(int pid) { id = pid;}
deba@57: 
deba@57:     public:
deba@57:       Edge() {}
deba@57:       Edge (Invalid) { id = -1; }
kpeter@73:       bool operator==(const Edge& edge) const {return id == edge.id;}
kpeter@73:       bool operator!=(const Edge& edge) const {return id != edge.id;}
kpeter@73:       bool operator<(const Edge& edge) const {return id < edge.id;}
deba@57:     };
deba@57: 
deba@57:     class Arc {
deba@57:       friend class ListGraphBase;
deba@57:     protected:
deba@57: 
deba@57:       int id;
deba@57:       explicit Arc(int pid) { id = pid;}
deba@57: 
deba@57:     public:
kpeter@329:       operator Edge() const {
kpeter@329:         return id != -1 ? edgeFromId(id / 2) : INVALID;
deba@238:       }
deba@57: 
deba@57:       Arc() {}
deba@57:       Arc (Invalid) { id = -1; }
deba@57:       bool operator==(const Arc& arc) const {return id == arc.id;}
deba@57:       bool operator!=(const Arc& arc) const {return id != arc.id;}
deba@57:       bool operator<(const Arc& arc) const {return id < arc.id;}
deba@57:     };
deba@57: 
deba@57: 
deba@57: 
deba@57:     ListGraphBase()
deba@57:       : nodes(), first_node(-1),
alpar@209:         first_free_node(-1), arcs(), first_free_arc(-1) {}
deba@57: 
alpar@209: 
alpar@209:     int maxNodeId() const { return nodes.size()-1; }
deba@57:     int maxEdgeId() const { return arcs.size() / 2 - 1; }
deba@57:     int maxArcId() const { return arcs.size()-1; }
deba@57: 
deba@57:     Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
deba@57:     Node target(Arc e) const { return Node(arcs[e.id].target); }
deba@57: 
deba@57:     Node u(Edge e) const { return Node(arcs[2 * e.id].target); }
deba@57:     Node v(Edge e) const { return Node(arcs[2 * e.id + 1].target); }
deba@57: 
deba@57:     static bool direction(Arc e) {
deba@57:       return (e.id & 1) == 1;
deba@57:     }
deba@57: 
deba@57:     static Arc direct(Edge e, bool d) {
deba@57:       return Arc(e.id * 2 + (d ? 1 : 0));
deba@57:     }
deba@57: 
alpar@209:     void first(Node& node) const {
deba@57:       node.id = first_node;
deba@57:     }
deba@57: 
deba@57:     void next(Node& node) const {
deba@57:       node.id = nodes[node.id].next;
deba@57:     }
deba@57: 
alpar@209:     void first(Arc& e) const {
deba@57:       int n = first_node;
deba@57:       while (n != -1 && nodes[n].first_out == -1) {
deba@57:         n = nodes[n].next;
deba@57:       }
deba@57:       e.id = (n == -1) ? -1 : nodes[n].first_out;
deba@57:     }
deba@57: 
deba@57:     void next(Arc& e) const {
deba@57:       if (arcs[e.id].next_out != -1) {
alpar@209:         e.id = arcs[e.id].next_out;
deba@57:       } else {
alpar@209:         int n = nodes[arcs[e.id ^ 1].target].next;
deba@57:         while(n != -1 && nodes[n].first_out == -1) {
deba@57:           n = nodes[n].next;
deba@57:         }
alpar@209:         e.id = (n == -1) ? -1 : nodes[n].first_out;
alpar@209:       }
deba@57:     }
deba@57: 
alpar@209:     void first(Edge& e) const {
deba@57:       int n = first_node;
deba@57:       while (n != -1) {
deba@57:         e.id = nodes[n].first_out;
deba@57:         while ((e.id & 1) != 1) {
deba@57:           e.id = arcs[e.id].next_out;
deba@57:         }
deba@57:         if (e.id != -1) {
deba@57:           e.id /= 2;
deba@57:           return;
alpar@209:         }
deba@57:         n = nodes[n].next;
deba@57:       }
deba@57:       e.id = -1;
deba@57:     }
deba@57: 
deba@57:     void next(Edge& e) const {
deba@57:       int n = arcs[e.id * 2].target;
deba@57:       e.id = arcs[(e.id * 2) | 1].next_out;
deba@57:       while ((e.id & 1) != 1) {
deba@57:         e.id = arcs[e.id].next_out;
deba@57:       }
deba@57:       if (e.id != -1) {
deba@57:         e.id /= 2;
deba@57:         return;
alpar@209:       }
deba@57:       n = nodes[n].next;
deba@57:       while (n != -1) {
deba@57:         e.id = nodes[n].first_out;
deba@57:         while ((e.id & 1) != 1) {
deba@57:           e.id = arcs[e.id].next_out;
deba@57:         }
deba@57:         if (e.id != -1) {
deba@57:           e.id /= 2;
deba@57:           return;
alpar@209:         }
deba@57:         n = nodes[n].next;
deba@57:       }
deba@57:       e.id = -1;
deba@57:     }
deba@57: 
deba@57:     void firstOut(Arc &e, const Node& v) const {
deba@57:       e.id = nodes[v.id].first_out;
deba@57:     }
deba@57:     void nextOut(Arc &e) const {
deba@57:       e.id = arcs[e.id].next_out;
deba@57:     }
deba@57: 
deba@57:     void firstIn(Arc &e, const Node& v) const {
deba@57:       e.id = ((nodes[v.id].first_out) ^ 1);
deba@57:       if (e.id == -2) e.id = -1;
deba@57:     }
deba@57:     void nextIn(Arc &e) const {
deba@57:       e.id = ((arcs[e.id ^ 1].next_out) ^ 1);
deba@57:       if (e.id == -2) e.id = -1;
deba@57:     }
deba@57: 
deba@57:     void firstInc(Edge &e, bool& d, const Node& v) const {
kpeter@73:       int a = nodes[v.id].first_out;
kpeter@73:       if (a != -1 ) {
kpeter@73:         e.id = a / 2;
kpeter@73:         d = ((a & 1) == 1);
deba@57:       } else {
deba@57:         e.id = -1;
deba@57:         d = true;
deba@57:       }
deba@57:     }
deba@57:     void nextInc(Edge &e, bool& d) const {
kpeter@73:       int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
kpeter@73:       if (a != -1 ) {
kpeter@73:         e.id = a / 2;
kpeter@73:         d = ((a & 1) == 1);
deba@57:       } else {
deba@57:         e.id = -1;
deba@57:         d = true;
deba@57:       }
deba@57:     }
alpar@209: 
deba@57:     static int id(Node v) { return v.id; }
deba@57:     static int id(Arc e) { return e.id; }
deba@57:     static int id(Edge e) { return e.id; }
deba@57: 
deba@57:     static Node nodeFromId(int id) { return Node(id);}
deba@57:     static Arc arcFromId(int id) { return Arc(id);}
deba@57:     static Edge edgeFromId(int id) { return Edge(id);}
deba@57: 
alpar@209:     bool valid(Node n) const {
alpar@209:       return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
alpar@209:         nodes[n.id].prev != -2;
deba@149:     }
deba@149: 
alpar@209:     bool valid(Arc a) const {
alpar@209:       return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
alpar@209:         arcs[a.id].prev_out != -2;
deba@149:     }
deba@149: 
alpar@209:     bool valid(Edge e) const {
alpar@209:       return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) &&
alpar@209:         arcs[2 * e.id].prev_out != -2;
deba@149:     }
deba@149: 
alpar@209:     Node addNode() {
deba@57:       int n;
alpar@209: 
deba@57:       if(first_free_node==-1) {
alpar@209:         n = nodes.size();
alpar@209:         nodes.push_back(NodeT());
deba@57:       } else {
alpar@209:         n = first_free_node;
alpar@209:         first_free_node = nodes[n].next;
deba@57:       }
alpar@209: 
deba@57:       nodes[n].next = first_node;
deba@57:       if (first_node != -1) nodes[first_node].prev = n;
deba@57:       first_node = n;
deba@57:       nodes[n].prev = -1;
alpar@209: 
deba@57:       nodes[n].first_out = -1;
alpar@209: 
deba@57:       return Node(n);
deba@57:     }
alpar@209: 
deba@57:     Edge addEdge(Node u, Node v) {
alpar@209:       int n;
deba@57: 
deba@57:       if (first_free_arc == -1) {
alpar@209:         n = arcs.size();
alpar@209:         arcs.push_back(ArcT());
alpar@209:         arcs.push_back(ArcT());
deba@57:       } else {
alpar@209:         n = first_free_arc;
alpar@209:         first_free_arc = arcs[n].next_out;
deba@57:       }
alpar@209: 
deba@57:       arcs[n].target = u.id;
deba@57:       arcs[n | 1].target = v.id;
deba@57: 
deba@57:       arcs[n].next_out = nodes[v.id].first_out;
deba@57:       if (nodes[v.id].first_out != -1) {
alpar@209:         arcs[nodes[v.id].first_out].prev_out = n;
alpar@209:       }
deba@57:       arcs[n].prev_out = -1;
deba@57:       nodes[v.id].first_out = n;
alpar@209: 
deba@57:       arcs[n | 1].next_out = nodes[u.id].first_out;
deba@57:       if (nodes[u.id].first_out != -1) {
alpar@209:         arcs[nodes[u.id].first_out].prev_out = (n | 1);
deba@57:       }
alpar@209:       arcs[n | 1].prev_out = -1;
deba@57:       nodes[u.id].first_out = (n | 1);
deba@57: 
deba@57:       return Edge(n / 2);
deba@57:     }
alpar@209: 
deba@57:     void erase(const Node& node) {
deba@57:       int n = node.id;
alpar@209: 
deba@57:       if(nodes[n].next != -1) {
alpar@209:         nodes[nodes[n].next].prev = nodes[n].prev;
deba@57:       }
alpar@209: 
deba@57:       if(nodes[n].prev != -1) {
alpar@209:         nodes[nodes[n].prev].next = nodes[n].next;
deba@57:       } else {
alpar@209:         first_node = nodes[n].next;
deba@57:       }
alpar@209: 
deba@57:       nodes[n].next = first_free_node;
deba@57:       first_free_node = n;
deba@149:       nodes[n].prev = -2;
deba@57:     }
alpar@209: 
kpeter@73:     void erase(const Edge& edge) {
kpeter@73:       int n = edge.id * 2;
alpar@209: 
deba@57:       if (arcs[n].next_out != -1) {
alpar@209:         arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
alpar@209:       }
deba@57: 
deba@57:       if (arcs[n].prev_out != -1) {
alpar@209:         arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
deba@57:       } else {
alpar@209:         nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
deba@57:       }
deba@57: 
deba@57:       if (arcs[n | 1].next_out != -1) {
alpar@209:         arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
alpar@209:       }
deba@57: 
deba@57:       if (arcs[n | 1].prev_out != -1) {
alpar@209:         arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
deba@57:       } else {
alpar@209:         nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
deba@57:       }
alpar@209: 
deba@57:       arcs[n].next_out = first_free_arc;
alpar@209:       first_free_arc = n;
deba@149:       arcs[n].prev_out = -2;
deba@149:       arcs[n | 1].prev_out = -2;
deba@57: 
deba@57:     }
deba@57: 
deba@57:     void clear() {
deba@57:       arcs.clear();
deba@57:       nodes.clear();
deba@57:       first_node = first_free_node = first_free_arc = -1;
deba@57:     }
deba@57: 
deba@57:   protected:
deba@57: 
deba@235:     void changeV(Edge e, Node n) {
deba@57:       if(arcs[2 * e.id].next_out != -1) {
alpar@209:         arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
deba@57:       }
deba@57:       if(arcs[2 * e.id].prev_out != -1) {
alpar@209:         arcs[arcs[2 * e.id].prev_out].next_out =
deba@57:           arcs[2 * e.id].next_out;
deba@57:       } else {
alpar@209:         nodes[arcs[(2 * e.id) | 1].target].first_out =
deba@57:           arcs[2 * e.id].next_out;
deba@57:       }
deba@57: 
deba@57:       if (nodes[n.id].first_out != -1) {
alpar@209:         arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
deba@57:       }
deba@57:       arcs[(2 * e.id) | 1].target = n.id;
deba@57:       arcs[2 * e.id].prev_out = -1;
deba@57:       arcs[2 * e.id].next_out = nodes[n.id].first_out;
deba@57:       nodes[n.id].first_out = 2 * e.id;
deba@57:     }
deba@57: 
deba@235:     void changeU(Edge e, Node n) {
deba@57:       if(arcs[(2 * e.id) | 1].next_out != -1) {
alpar@209:         arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
deba@57:           arcs[(2 * e.id) | 1].prev_out;
deba@57:       }
deba@57:       if(arcs[(2 * e.id) | 1].prev_out != -1) {
alpar@209:         arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
deba@57:           arcs[(2 * e.id) | 1].next_out;
deba@57:       } else {
alpar@209:         nodes[arcs[2 * e.id].target].first_out =
deba@57:           arcs[(2 * e.id) | 1].next_out;
deba@57:       }
deba@57: 
deba@57:       if (nodes[n.id].first_out != -1) {
alpar@209:         arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
deba@57:       }
deba@57:       arcs[2 * e.id].target = n.id;
deba@57:       arcs[(2 * e.id) | 1].prev_out = -1;
deba@57:       arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
deba@57:       nodes[n.id].first_out = ((2 * e.id) | 1);
deba@57:     }
deba@57: 
deba@57:   };
deba@57: 
deba@57:   typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
deba@57: 
deba@57: 
kpeter@73:   /// \addtogroup graphs
deba@57:   /// @{
deba@57: 
kpeter@73:   ///A general undirected graph structure.
deba@57: 
alpar@209:   ///\ref ListGraph is a simple and fast <em>undirected graph</em>
alpar@209:   ///implementation based on static linked lists that are stored in
alpar@209:   ///\c std::vector structures.
deba@57:   ///
kpeter@73:   ///It conforms to the \ref concepts::Graph "Graph concept" and it
kpeter@73:   ///also provides several useful additional functionalities.
kpeter@73:   ///Most of the member functions and nested classes are documented
kpeter@73:   ///only in the concept class.
kpeter@73:   ///
kpeter@73:   ///An important extra feature of this graph implementation is that
deba@57:   ///its maps are real \ref concepts::ReferenceMap "reference map"s.
deba@57:   ///
kpeter@73:   ///\sa concepts::Graph
kpeter@73: 
deba@57:   class ListGraph : public ExtendedListGraphBase {
deba@57:   private:
kpeter@73:     ///ListGraph is \e not copy constructible. Use copyGraph() instead.
deba@57: 
kpeter@73:     ///ListGraph is \e not copy constructible. Use copyGraph() instead.
deba@57:     ///
deba@57:     ListGraph(const ListGraph &) :ExtendedListGraphBase()  {};
deba@57:     ///\brief Assignment of ListGraph to another one is \e not allowed.
kpeter@73:     ///Use copyGraph() instead.
deba@57: 
deba@57:     ///Assignment of ListGraph to another one is \e not allowed.
kpeter@73:     ///Use copyGraph() instead.
deba@57:     void operator=(const ListGraph &) {}
deba@57:   public:
deba@57:     /// Constructor
alpar@209: 
deba@57:     /// Constructor.
deba@57:     ///
deba@57:     ListGraph() {}
deba@57: 
deba@57:     typedef ExtendedListGraphBase Parent;
deba@57: 
kpeter@73:     typedef Parent::OutArcIt IncEdgeIt;
deba@57: 
kpeter@73:     /// \brief Add a new node to the graph.
deba@57:     ///
kpeter@73:     /// Add a new node to the graph.
deba@57:     /// \return the new node.
deba@57:     Node addNode() { return Parent::addNode(); }
deba@57: 
kpeter@73:     /// \brief Add a new edge to the graph.
deba@57:     ///
kpeter@73:     /// Add a new edge to the graph with source node \c s
deba@57:     /// and target node \c t.
deba@57:     /// \return the new edge.
alpar@209:     Edge addEdge(const Node& s, const Node& t) {
alpar@209:       return Parent::addEdge(s, t);
deba@57:     }
deba@234: 
deba@234:     /// \brief Erase a node from the graph.
deba@234:     ///
deba@234:     /// Erase a node from the graph.
deba@234:     ///
deba@234:     void erase(const Node& n) { Parent::erase(n); }
deba@234: 
deba@234:     /// \brief Erase an edge from the graph.
deba@234:     ///
deba@234:     /// Erase an edge from the graph.
deba@234:     ///
deba@234:     void erase(const Edge& e) { Parent::erase(e); }
deba@149:     /// Node validity check
deba@149: 
deba@149:     /// This function gives back true if the given node is valid,
alpar@209:     /// ie. it is a real node of the graph.
deba@149:     ///
deba@149:     /// \warning A Node pointing to a removed item
deba@149:     /// could become valid again later if new nodes are
deba@149:     /// added to the graph.
deba@149:     bool valid(Node n) const { return Parent::valid(n); }
deba@149:     /// Arc validity check
deba@149: 
deba@149:     /// This function gives back true if the given arc is valid,
alpar@209:     /// ie. it is a real arc of the graph.
deba@149:     ///
deba@149:     /// \warning An Arc pointing to a removed item
deba@149:     /// could become valid again later if new edges are
deba@149:     /// added to the graph.
deba@149:     bool valid(Arc a) const { return Parent::valid(a); }
deba@149:     /// Edge validity check
deba@149: 
deba@149:     /// This function gives back true if the given edge is valid,
alpar@209:     /// ie. it is a real arc of the graph.
deba@149:     ///
deba@149:     /// \warning A Edge pointing to a removed item
deba@149:     /// could become valid again later if new edges are
deba@149:     /// added to the graph.
deba@149:     bool valid(Edge e) const { return Parent::valid(e); }
deba@235:     /// \brief Change the end \c u of \c e to \c n
deba@57:     ///
deba@235:     /// This function changes the end \c u of \c e to node \c n.
deba@57:     ///
deba@235:     ///\note The <tt>EdgeIt</tt>s and <tt>ArcIt</tt>s referencing the
deba@235:     ///changed edge are invalidated and if the changed node is the
deba@235:     ///base node of an iterator then this iterator is also
deba@235:     ///invalidated.
kpeter@73:     ///
kpeter@73:     ///\warning This functionality cannot be used together with the
kpeter@73:     ///Snapshot feature.
deba@235:     void changeU(Edge e, Node n) {
deba@235:       Parent::changeU(e,n);
alpar@209:     }
deba@235:     /// \brief Change the end \c v of \c e to \c n
deba@57:     ///
deba@235:     /// This function changes the end \c v of \c e to \c n.
deba@57:     ///
deba@235:     ///\note The <tt>EdgeIt</tt>s referencing the changed edge remain
deba@235:     ///valid, however <tt>ArcIt</tt>s and if the changed node is the
deba@235:     ///base node of an iterator then this iterator is invalidated.
kpeter@73:     ///
kpeter@73:     ///\warning This functionality cannot be used together with the
kpeter@73:     ///Snapshot feature.
deba@235:     void changeV(Edge e, Node n) {
deba@235:       Parent::changeV(e,n);
deba@57:     }
deba@57:     /// \brief Contract two nodes.
deba@57:     ///
deba@57:     /// This function contracts two nodes.
deba@57:     /// Node \p b will be removed but instead of deleting
deba@57:     /// its neighboring arcs, they will be joined to \p a.
deba@57:     /// The last parameter \p r controls whether to remove loops. \c true
deba@57:     /// means that loops will be removed.
deba@57:     ///
deba@57:     /// \note The <tt>ArcIt</tt>s referencing a moved arc remain
deba@57:     /// valid.
kpeter@73:     ///
kpeter@73:     ///\warning This functionality cannot be used together with the
kpeter@73:     ///Snapshot feature.
deba@57:     void contract(Node a, Node b, bool r = true) {
kpeter@73:       for(IncEdgeIt e(*this, b); e!=INVALID;) {
alpar@209:         IncEdgeIt f = e; ++f;
alpar@209:         if (r && runningNode(e) == a) {
alpar@209:           erase(e);
deba@235:         } else if (u(e) == b) {
deba@235:           changeU(e, a);
alpar@209:         } else {
deba@235:           changeV(e, a);
alpar@209:         }
alpar@209:         e = f;
deba@57:       }
deba@57:       erase(b);
deba@57:     }
deba@57: 
deba@57: 
kpeter@73:     /// \brief Class to make a snapshot of the graph and restore
kpeter@73:     /// it later.
deba@57:     ///
kpeter@73:     /// Class to make a snapshot of the graph and restore it later.
deba@57:     ///
deba@57:     /// The newly added nodes and edges can be removed
deba@57:     /// using the restore() function.
deba@57:     ///
kpeter@73:     /// \warning Edge and node deletions and other modifications
alpar@209:     /// (e.g. changing nodes of edges, contracting nodes) cannot be
kpeter@73:     /// restored. These events invalidate the snapshot.
deba@57:     class Snapshot {
deba@57:     protected:
deba@57: 
deba@57:       typedef Parent::NodeNotifier NodeNotifier;
deba@57: 
deba@57:       class NodeObserverProxy : public NodeNotifier::ObserverBase {
deba@57:       public:
deba@57: 
deba@57:         NodeObserverProxy(Snapshot& _snapshot)
deba@57:           : snapshot(_snapshot) {}
deba@57: 
deba@57:         using NodeNotifier::ObserverBase::attach;
deba@57:         using NodeNotifier::ObserverBase::detach;
deba@57:         using NodeNotifier::ObserverBase::attached;
alpar@209: 
deba@57:       protected:
alpar@209: 
deba@57:         virtual void add(const Node& node) {
deba@57:           snapshot.addNode(node);
deba@57:         }
deba@57:         virtual void add(const std::vector<Node>& nodes) {
deba@57:           for (int i = nodes.size() - 1; i >= 0; ++i) {
deba@57:             snapshot.addNode(nodes[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void erase(const Node& node) {
deba@57:           snapshot.eraseNode(node);
deba@57:         }
deba@57:         virtual void erase(const std::vector<Node>& nodes) {
deba@57:           for (int i = 0; i < int(nodes.size()); ++i) {
deba@57:             snapshot.eraseNode(nodes[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void build() {
deba@57:           Node node;
deba@57:           std::vector<Node> nodes;
alpar@209:           for (notifier()->first(node); node != INVALID;
deba@57:                notifier()->next(node)) {
deba@57:             nodes.push_back(node);
deba@57:           }
deba@57:           for (int i = nodes.size() - 1; i >= 0; --i) {
deba@57:             snapshot.addNode(nodes[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void clear() {
deba@57:           Node node;
alpar@209:           for (notifier()->first(node); node != INVALID;
deba@57:                notifier()->next(node)) {
deba@57:             snapshot.eraseNode(node);
deba@57:           }
deba@57:         }
deba@57: 
deba@57:         Snapshot& snapshot;
deba@57:       };
deba@57: 
deba@57:       class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
deba@57:       public:
deba@57: 
deba@57:         EdgeObserverProxy(Snapshot& _snapshot)
deba@57:           : snapshot(_snapshot) {}
deba@57: 
deba@57:         using EdgeNotifier::ObserverBase::attach;
deba@57:         using EdgeNotifier::ObserverBase::detach;
deba@57:         using EdgeNotifier::ObserverBase::attached;
alpar@209: 
deba@57:       protected:
deba@57: 
kpeter@73:         virtual void add(const Edge& edge) {
kpeter@73:           snapshot.addEdge(edge);
deba@57:         }
kpeter@73:         virtual void add(const std::vector<Edge>& edges) {
kpeter@73:           for (int i = edges.size() - 1; i >= 0; ++i) {
kpeter@73:             snapshot.addEdge(edges[i]);
deba@57:           }
deba@57:         }
kpeter@73:         virtual void erase(const Edge& edge) {
kpeter@73:           snapshot.eraseEdge(edge);
deba@57:         }
kpeter@73:         virtual void erase(const std::vector<Edge>& edges) {
kpeter@73:           for (int i = 0; i < int(edges.size()); ++i) {
kpeter@73:             snapshot.eraseEdge(edges[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void build() {
kpeter@73:           Edge edge;
kpeter@73:           std::vector<Edge> edges;
alpar@209:           for (notifier()->first(edge); edge != INVALID;
kpeter@73:                notifier()->next(edge)) {
kpeter@73:             edges.push_back(edge);
deba@57:           }
kpeter@73:           for (int i = edges.size() - 1; i >= 0; --i) {
kpeter@73:             snapshot.addEdge(edges[i]);
deba@57:           }
deba@57:         }
deba@57:         virtual void clear() {
kpeter@73:           Edge edge;
alpar@209:           for (notifier()->first(edge); edge != INVALID;
kpeter@73:                notifier()->next(edge)) {
kpeter@73:             snapshot.eraseEdge(edge);
deba@57:           }
deba@57:         }
deba@57: 
deba@57:         Snapshot& snapshot;
deba@57:       };
kpeter@73: 
kpeter@73:       ListGraph *graph;
deba@57: 
deba@57:       NodeObserverProxy node_observer_proxy;
kpeter@73:       EdgeObserverProxy edge_observer_proxy;
deba@57: 
deba@57:       std::list<Node> added_nodes;
kpeter@73:       std::list<Edge> added_edges;
deba@57: 
deba@57: 
deba@57:       void addNode(const Node& node) {
alpar@209:         added_nodes.push_front(node);
deba@57:       }
deba@57:       void eraseNode(const Node& node) {
alpar@209:         std::list<Node>::iterator it =
deba@57:           std::find(added_nodes.begin(), added_nodes.end(), node);
deba@57:         if (it == added_nodes.end()) {
deba@57:           clear();
kpeter@73:           edge_observer_proxy.detach();
deba@57:           throw NodeNotifier::ImmediateDetach();
deba@57:         } else {
deba@57:           added_nodes.erase(it);
deba@57:         }
deba@57:       }
deba@57: 
kpeter@73:       void addEdge(const Edge& edge) {
alpar@209:         added_edges.push_front(edge);
deba@57:       }
kpeter@73:       void eraseEdge(const Edge& edge) {
alpar@209:         std::list<Edge>::iterator it =
kpeter@73:           std::find(added_edges.begin(), added_edges.end(), edge);
kpeter@73:         if (it == added_edges.end()) {
deba@57:           clear();
deba@57:           node_observer_proxy.detach();
deba@57:           throw EdgeNotifier::ImmediateDetach();
deba@57:         } else {
kpeter@73:           added_edges.erase(it);
kpeter@73:         }
deba@57:       }
deba@57: 
kpeter@73:       void attach(ListGraph &_graph) {
alpar@209:         graph = &_graph;
alpar@209:         node_observer_proxy.attach(graph->notifier(Node()));
kpeter@73:         edge_observer_proxy.attach(graph->notifier(Edge()));
deba@57:       }
alpar@209: 
deba@57:       void detach() {
alpar@209:         node_observer_proxy.detach();
alpar@209:         edge_observer_proxy.detach();
deba@57:       }
deba@57: 
deba@57:       bool attached() const {
deba@57:         return node_observer_proxy.attached();
deba@57:       }
deba@57: 
deba@57:       void clear() {
deba@57:         added_nodes.clear();
alpar@209:         added_edges.clear();
deba@57:       }
deba@57: 
deba@57:     public:
deba@57: 
deba@57:       /// \brief Default constructor.
deba@57:       ///
deba@57:       /// Default constructor.
deba@57:       /// To actually make a snapshot you must call save().
alpar@209:       Snapshot()
alpar@209:         : graph(0), node_observer_proxy(*this),
kpeter@73:           edge_observer_proxy(*this) {}
alpar@209: 
deba@57:       /// \brief Constructor that immediately makes a snapshot.
alpar@209:       ///
kpeter@73:       /// This constructor immediately makes a snapshot of the graph.
kpeter@73:       /// \param _graph The graph we make a snapshot of.
alpar@209:       Snapshot(ListGraph &_graph)
alpar@209:         : node_observer_proxy(*this),
kpeter@73:           edge_observer_proxy(*this) {
alpar@209:         attach(_graph);
deba@57:       }
alpar@209: 
deba@57:       /// \brief Make a snapshot.
deba@57:       ///
kpeter@73:       /// Make a snapshot of the graph.
deba@57:       ///
deba@57:       /// This function can be called more than once. In case of a repeated
deba@57:       /// call, the previous snapshot gets lost.
kpeter@73:       /// \param _graph The graph we make the snapshot of.
kpeter@73:       void save(ListGraph &_graph) {
deba@57:         if (attached()) {
deba@57:           detach();
deba@57:           clear();
deba@57:         }
kpeter@73:         attach(_graph);
deba@57:       }
alpar@209: 
deba@57:       /// \brief Undo the changes until the last snapshot.
alpar@209:       //
deba@57:       /// Undo the changes until the last snapshot created by save().
deba@57:       void restore() {
alpar@209:         detach();
alpar@209:         for(std::list<Edge>::iterator it = added_edges.begin();
kpeter@73:             it != added_edges.end(); ++it) {
alpar@209:           graph->erase(*it);
alpar@209:         }
alpar@209:         for(std::list<Node>::iterator it = added_nodes.begin();
deba@57:             it != added_nodes.end(); ++it) {
alpar@209:           graph->erase(*it);
alpar@209:         }
deba@57:         clear();
deba@57:       }
deba@57: 
deba@57:       /// \brief Gives back true when the snapshot is valid.
deba@57:       ///
deba@57:       /// Gives back true when the snapshot is valid.
deba@57:       bool valid() const {
deba@57:         return attached();
deba@57:       }
deba@57:     };
deba@57:   };
alpar@209: 
alpar@209:   /// @}
deba@57: } //namespace lemon
alpar@209: 
deba@57: 
deba@57: #endif