COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2114:677ea6c8169a

Last change on this file since 2114:677ea6c8169a was 2114:677ea6c8169a, checked in by Balazs Dezso, 18 years ago

new snapshot

File size: 30.9 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
[1909]24///\brief ListGraph, ListUGraph classes.
[948]25
[1999]26#include <lemon/bits/base_extender.h>
[1791]27#include <lemon/bits/graph_extender.h>
[782]28
[1774]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
[813]169    /// \warning It adds the new node to the front of the list.
[397]170    /// (i.e. the lastly added node becomes the first.)
[946]171    Node addNode() {     
[397]172      int n;
173     
[946]174      if(first_free_node==-1) {
175        n = nodes.size();
176        nodes.push_back(NodeT());
177      } else {
[397]178        n = first_free_node;
179        first_free_node = nodes[n].next;
180      }
181     
182      nodes[n].next = first_node;
183      if(first_node != -1) nodes[first_node].prev = n;
184      first_node = n;
185      nodes[n].prev = -1;
186     
187      nodes[n].first_in = nodes[n].first_out = -1;
188     
[946]189      return Node(n);
[395]190    }
191   
192    Edge addEdge(Node u, Node v) {
[946]193      int n;     
194
195      if (first_free_edge == -1) {
196        n = edges.size();
197        edges.push_back(EdgeT());
198      } else {
[397]199        n = first_free_edge;
200        first_free_edge = edges[n].next_in;
201      }
202     
[986]203      edges[n].source = u.id;
204      edges[n].target = v.id;
[395]205
[946]206      edges[n].next_out = nodes[u.id].first_out;
207      if(nodes[u.id].first_out != -1) {
208        edges[nodes[u.id].first_out].prev_out = n;
209      }
210     
211      edges[n].next_in = nodes[v.id].first_in;
212      if(nodes[v.id].first_in != -1) {
213        edges[nodes[v.id].first_in].prev_in = n;
214      }
215     
[397]216      edges[n].prev_in = edges[n].prev_out = -1;
217       
[946]218      nodes[u.id].first_out = nodes[v.id].first_in = n;
[397]219
[946]220      return Edge(n);
[395]221    }
[774]222   
[946]223    void erase(const Node& node) {
224      int n = node.id;
225     
226      if(nodes[n].next != -1) {
227        nodes[nodes[n].next].prev = nodes[n].prev;
228      }
229     
230      if(nodes[n].prev != -1) {
231        nodes[nodes[n].prev].next = nodes[n].next;
232      } else {
233        first_node = nodes[n].next;
234      }
235     
236      nodes[n].next = first_free_node;
237      first_free_node = n;
[395]238
[774]239    }
240   
[946]241    void erase(const Edge& edge) {
242      int n = edge.id;
[397]243     
[946]244      if(edges[n].next_in!=-1) {
[397]245        edges[edges[n].next_in].prev_in = edges[n].prev_in;
[946]246      }
247
248      if(edges[n].prev_in!=-1) {
[397]249        edges[edges[n].prev_in].next_in = edges[n].next_in;
[946]250      } else {
[986]251        nodes[edges[n].target].first_in = edges[n].next_in;
[946]252      }
253
[397]254     
[946]255      if(edges[n].next_out!=-1) {
[397]256        edges[edges[n].next_out].prev_out = edges[n].prev_out;
[946]257      }
258
259      if(edges[n].prev_out!=-1) {
[397]260        edges[edges[n].prev_out].next_out = edges[n].next_out;
[946]261      } else {
[986]262        nodes[edges[n].source].first_out = edges[n].next_out;
[946]263      }
[397]264     
265      edges[n].next_in = first_free_edge;
[695]266      first_free_edge = n;     
[397]267
268    }
269
270    void clear() {
[782]271      edges.clear();
272      nodes.clear();
[946]273      first_node = first_free_node = first_free_edge = -1;
[937]274    }
275
[949]276  protected:
[2111]277    void changeTarget(Edge e, Node n)
[949]278    {
279      if(edges[e.id].next_in != -1)
280        edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
281      if(edges[e.id].prev_in != -1)
282        edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
[986]283      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
[1702]284      if (nodes[n.id].first_in != -1) {
285        edges[nodes[n.id].first_in].prev_in = e.id;
286      }
[986]287      edges[e.id].target = n.id;
[949]288      edges[e.id].prev_in = -1;
289      edges[e.id].next_in = nodes[n.id].first_in;
290      nodes[n.id].first_in = e.id;
291    }
[2111]292    void changeSource(Edge e, Node n)
[949]293    {
294      if(edges[e.id].next_out != -1)
295        edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
296      if(edges[e.id].prev_out != -1)
297        edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
[986]298      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
[1702]299      if (nodes[n.id].first_out != -1) {
300        edges[nodes[n.id].first_out].prev_out = e.id;
301      }
[986]302      edges[e.id].source = n.id;
[949]303      edges[e.id].prev_out = -1;
304      edges[e.id].next_out = nodes[n.id].first_out;
305      nodes[n.id].first_out = e.id;
306    }
307
[919]308  };
[909]309
[1979]310  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
[400]311
[1718]312  /// \addtogroup graphs
313  /// @{
[400]314
[948]315  ///A list graph class.
[400]316
[948]317  ///This is a simple and fast erasable graph implementation.
318  ///
[2111]319  ///It conforms to the \ref concept::Graph "Graph" concept and it
320  ///also provides several additional useful extra functionalities.
321  ///The most of the member functions and nested classes are
322  ///documented only in the concept class.
323  ///\sa concept::Graph.
[782]324
[1999]325  class ListGraph : public ExtendedListGraphBase {
[948]326  public:
[1999]327
328    typedef ExtendedListGraphBase Parent;
329
[2111]330    ///Add a new node to the graph.
331   
332    /// \return the new node.
333    ///
334    Node addNode() { return Parent::addNode(); }
335
336    ///Add a new edge to the graph.
337   
338    ///Add a new edge to the graph with source node \c s
339    ///and target node \c t.
340    ///\return the new edge.
341    Edge addEdge(const Node& s, const Node& t) {
342      return Parent::addEdge(s, t);
343    }
344
[1546]345    /// Changes the target of \c e to \c n
[948]346
[1546]347    /// Changes the target of \c e to \c n
[948]348    ///
[2114]349    ///\note The <tt>Edge</tt>s and <tt>OutEdgeIt</tt>s referencing
350    ///the changed edge remain valid. However <tt>InEdgeIt</tt>s are
351    ///invalidated.
[1718]352    void changeTarget(Edge e, Node n) {
[2111]353      Parent::changeTarget(e,n);
[1718]354    }
[1546]355    /// Changes the source of \c e to \c n
[948]356
[1546]357    /// Changes the source of \c e to \c n
[948]358    ///
[2114]359    ///\note The <tt>Edge</tt>s and <tt>InEdgeIt</tt>s referencing
360    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are
361    ///invalidated.
[1718]362    void changeSource(Edge e, Node n) {
[2111]363      Parent::changeSource(e,n);
[1718]364    }
[949]365
[1010]366    /// Invert the direction of an edge.
367
[2114]368    ///\note The <tt>Edge</tt>s referencing the changed edge remain
369    ///valid. However <tt>OutEdgeIt</tt>s and <tt>InEdgeIt</tt>s are
370    ///invalidated.
[1010]371    void reverseEdge(Edge e) {
372      Node t=target(e);
[2111]373      changeTarget(e,source(e));
374      changeSource(e,t);
[1010]375    }
376
[2111]377    /// \brief Using this it is possible to avoid the superfluous memory
378    /// allocation.
[1010]379
[2107]380    ///Using this it is possible to avoid the superfluous memory
381    ///allocation: if you know that the graph you want to build will
382    ///contain at least 10 million nodes then it is worth to reserve
383    ///space for this amount before starting to build the graph.
384    void reserveNode(int n) { nodes.reserve(n); };
385
[2111]386    /// \brief Using this it is possible to avoid the superfluous memory
387    /// allocation.
[2107]388
389    ///Using this it is possible to avoid the superfluous memory
390    ///allocation: see the \ref reserveNode function.
[949]391    void reserveEdge(int n) { edges.reserve(n); };
[1010]392
[2107]393
[1010]394    ///Contract two nodes.
395
396    ///This function contracts two nodes.
397    ///
398    ///Node \p b will be removed but instead of deleting
[2102]399    ///incident edges, they will be joined to \p a.
[1010]400    ///The last parameter \p r controls whether to remove loops. \c true
401    ///means that loops will be removed.
402    ///
403    ///\note The <tt>Edge</tt>s
[1281]404    ///referencing a moved edge remain
[2102]405    ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
[1010]406    ///may be invalidated.
[1718]407    void contract(Node a, Node b, bool r = true)
[1010]408    {
409      for(OutEdgeIt e(*this,b);e!=INVALID;) {
410        OutEdgeIt f=e;
411        ++f;
412        if(r && target(e)==a) erase(e);
[1546]413        else changeSource(e,a);
[1010]414        e=f;
415      }
416      for(InEdgeIt e(*this,b);e!=INVALID;) {
417        InEdgeIt f=e;
418        ++f;
419        if(r && source(e)==a) erase(e);
[1546]420        else changeTarget(e,a);
[1010]421        e=f;
422      }
423      erase(b);
424    }
[1011]425
[1281]426    ///Split a node.
[1011]427
[1284]428    ///This function splits a node. First a new node is added to the graph,
429    ///then the source of each outgoing edge of \c n is moved to this new node.
[1281]430    ///If \c connect is \c true (this is the default value), then a new edge
431    ///from \c n to the newly created node is also added.
432    ///\return The newly created node.
433    ///
434    ///\note The <tt>Edge</tt>s
435    ///referencing a moved edge remain
[2102]436    ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
[1281]437    ///may be invalidated.
[1770]438    ///\warning This functionality cannot be used together with the Snapshot
[1284]439    ///feature.
[1281]440    ///\todo It could be implemented in a bit faster way.
[2114]441    Node split(Node n, bool connect = true) {
[1281]442      Node b = addNode();
443      for(OutEdgeIt e(*this,n);e!=INVALID;) {
444        OutEdgeIt f=e;
445        ++f;
[1546]446        changeSource(e,b);
[1281]447        e=f;
448      }
[2114]449      if (connect) addEdge(n,b);
[1281]450      return b;
451    }
452     
[1812]453    ///Split an edge.
454
[2102]455    ///This function splits an edge. First a new node \c b is added to
456    ///the graph, then the original edge is re-targeted to \c
457    ///b. Finally an edge from \c b to the original target is added.
458    ///\return The newly created node. 
459    ///\warning This functionality
460    ///cannot be used together with the Snapshot feature.
[2114]461    Node split(Edge e) {
[1812]462      Node b = addNode();
463      addEdge(b,target(e));
464      changeTarget(e,b);
465      return b;
466    }
467     
[2114]468    /// \brief Class to make a snapshot of the graph and restore
469    /// to it later.
[1011]470    ///
[2114]471    /// Class to make a snapshot of the graph and to restore it
472    /// later.
[1011]473    ///
[2114]474    /// The newly added nodes and edges can be removed using the
475    /// restore() function.
476    ///
477    /// \warning Edge and node deletions cannot be restored.
478    class Snapshot {
[1774]479    public:
480     
481      class UnsupportedOperation : public LogicError {
482      public:
483        virtual const char* exceptionName() const {
484          return "lemon::ListGraph::Snapshot::UnsupportedOperation";
485        }
486      };
487           
488
[1999]489    protected:
[2114]490
491      typedef Parent::NodeNotifier NodeNotifier;
492
493      class NodeObserverProxy : public NodeNotifier::ObserverBase {
494      public:
495
496        NodeObserverProxy(Snapshot& _snapshot)
497          : snapshot(_snapshot) {}
498
499        using NodeNotifier::ObserverBase::attach;
500        using NodeNotifier::ObserverBase::detach;
501        using NodeNotifier::ObserverBase::attached;
502       
503      protected:
504       
505        virtual void add(const Node& node) {
506          snapshot.addNode(node);
507        }
508        virtual void add(const std::vector<Node>& nodes) {
509          for (int i = nodes.size() - 1; i >= 0; ++i) {
510            snapshot.addNode(nodes[i]);
511          }
512        }
513        virtual void erase(const Node& node) {
514          snapshot.eraseNode(node);
515        }
516        virtual void erase(const std::vector<Node>& nodes) {
517          for (int i = 0; i < (int)nodes.size(); ++i) {
518            if (!snapshot.eraseNode(nodes[i])) break;
519          }
520        }
521        virtual void build() {
522          NodeNotifier* notifier = getNotifier();
523          Node node;
524          std::vector<Node> nodes;
525          for (notifier->first(node); node != INVALID; notifier->next(node)) {
526            nodes.push_back(node);
527          }
528          for (int i = nodes.size() - 1; i >= 0; --i) {
529            snapshot.addNode(nodes[i]);
530          }
531        }
532        virtual void clear() {
533          NodeNotifier* notifier = getNotifier();
534          Node node;
535          for (notifier->first(node); node != INVALID; notifier->next(node)) {
536            if (!snapshot.eraseNode(node)) break;
537          }
538        }
539
540        Snapshot& snapshot;
541      };
542
543      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
544      public:
545
546        EdgeObserverProxy(Snapshot& _snapshot)
547          : snapshot(_snapshot) {}
548
549        using EdgeNotifier::ObserverBase::attach;
550        using EdgeNotifier::ObserverBase::detach;
551        using EdgeNotifier::ObserverBase::attached;
552       
553      protected:
554
555        virtual void add(const Edge& edge) {
556          snapshot.addEdge(edge);
557        }
558        virtual void add(const std::vector<Edge>& edges) {
559          for (int i = edges.size() - 1; i >= 0; ++i) {
560            snapshot.addEdge(edges[i]);
561          }
562        }
563        virtual void erase(const Edge& edge) {
564          snapshot.eraseEdge(edge);
565        }
566        virtual void erase(const std::vector<Edge>& edges) {
567          for (int i = 0; i < (int)edges.size(); ++i) {
568            if (!snapshot.eraseEdge(edges[i])) break;
569          }
570        }
571        virtual void build() {
572          EdgeNotifier* notifier = getNotifier();
573          Edge edge;
574          std::vector<Edge> edges;
575          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
576            edges.push_back(edge);
577          }
578          for (int i = edges.size() - 1; i >= 0; --i) {
579            snapshot.addEdge(edges[i]);
580          }
581        }
582        virtual void clear() {
583          EdgeNotifier* notifier = getNotifier();
584          Edge edge;
585          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
586            if (!snapshot.eraseEdge(edge)) break;
587          }
588        }
589
590        Snapshot& snapshot;
591      };
[1011]592     
[2114]593      ListGraph *graph;
594
595      NodeObserverProxy node_observer_proxy;
596      EdgeObserverProxy edge_observer_proxy;
597
[1011]598      std::list<Node> added_nodes;
599      std::list<Edge> added_edges;
[2114]600
601
602      void addNode(const Node& node) {
603        added_nodes.push_front(node);       
[1011]604      }
[2114]605      bool eraseNode(const Node& node) {
606        std::list<Node>::iterator it =
607          std::find(added_nodes.begin(), added_nodes.end(), node);
608        if (it == added_nodes.end()) {
609          clear();
610          return false;
611        } else {
612          added_nodes.erase(it);
613          return true;
614        }
[1011]615      }
616
[2114]617      void addEdge(const Edge& edge) {
618        added_edges.push_front(edge);       
619      }
620      bool eraseEdge(const Edge& edge) {
621        std::list<Edge>::iterator it =
622          std::find(added_edges.begin(), added_edges.end(), edge);
623        if (it == added_edges.end()) {
624          clear();
625          return false;
626        } else {
627          added_edges.erase(it);
628          return true;
629        }       
630      }
[1457]631
[2114]632      void attach(ListGraph &_graph) {
633        graph = &_graph;
634        node_observer_proxy.attach(graph->getNotifier(Node()));
635        edge_observer_proxy.attach(graph->getNotifier(Edge()));
[1011]636      }
637           
[2114]638      void detach() {
639        node_observer_proxy.detach();
640        edge_observer_proxy.detach();
641      }
642
643      void clear() {
644        detach();
645        added_nodes.clear();
646        added_edges.clear();       
[1011]647      }
[1774]648
[1011]649    public:
[2114]650
651      /// \brief Default constructur.
652      ///
653      /// Default constructor.
654      /// To actually make a snapshot you must call save().
655      Snapshot()
656        : graph(0), node_observer_proxy(*this),
657          edge_observer_proxy(*this) {}
[1011]658     
[2114]659      /// \brief Constructor that immediately makes a snapshot.
660      ///     
661      /// This constructor immediately makes a snapshot of the graph.
662      /// \param _graph The graph we make a snapshot of.
663      Snapshot(ListGraph &_graph)
664        : node_observer_proxy(*this),
665          edge_observer_proxy(*this) {
666        attach(_graph);
[1011]667      }
668     
[2114]669      /// \brief Make a snapshot.
[1011]670      ///
[2114]671      /// Make a snapshot of the graph.
672      ///
673      /// This function can be called more than once. In case of a repeated
674      /// call, the previous snapshot gets lost.
675      /// \param _graph The graph we make the snapshot of.
676      void save(ListGraph &_graph) {
677        clear();
678        attach(_graph);
[1011]679      }
680     
[2114]681      /// \brief Undo the changes until the last snapshot.
682      //
683      /// Undo the changes until last snapshot created by save().
684      ///
685      /// \todo This function might be called undo().
[1011]686      void restore() {
[2114]687        detach();
[1011]688        while(!added_edges.empty()) {
[2114]689          graph->erase(added_edges.front());
[1011]690          added_edges.pop_front();
691        }
692        while(!added_nodes.empty()) {
[2114]693          graph->erase(added_nodes.front());
[1011]694          added_nodes.pop_front();
695        }
696      }
[2114]697
698      /// \brief Gives back true when the snapshot is valid.
699      ///
700      /// Gives back true when the snapshot is valid.
701      bool valid() const {
702        return node_observer_proxy.attached();
703      }
[1011]704    };
705   
[949]706  };
[1034]707
[1555]708  ///@}
[1034]709
710  /**************** Undirected List Graph ****************/
711
[2076]712  typedef UGraphExtender<UndirGraphExtender<ListGraphBase> >
713  ExtendedListUGraphBase;
[1034]714
[1718]715  /// \addtogroup graphs
716  /// @{
[1555]717
[1035]718  ///An undirected list graph class.
719
720  ///This is a simple and fast erasable undirected graph implementation.
721  ///
722  ///It conforms to the
[1909]723  ///\ref concept::UGraph "UGraph" concept.
[1035]724  ///
[1909]725  ///\sa concept::UGraph.
[1035]726  ///
[1770]727  ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
[1161]728  ///haven't been implemented yet.
[1035]729  ///
[1909]730  class ListUGraph : public ExtendedListUGraphBase {
[1718]731  public:
[1909]732    typedef ExtendedListUGraphBase Parent;
[2111]733    /// \brief Add a new node to the graph.
734    ///
735    /// \return the new node.
736    ///
737    Node addNode() { return Parent::addNode(); }
738
739    /// \brief Add a new edge to the graph.
740    ///
741    /// Add a new edge to the graph with source node \c s
742    /// and target node \c t.
743    /// \return the new undirected edge.
744    UEdge addEdge(const Node& s, const Node& t) {
745      return Parent::addEdge(s, t);
746    }
[1718]747    /// \brief Changes the target of \c e to \c n
748    ///
749    /// Changes the target of \c e to \c n
750    ///
751    /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
752    /// referencing the changed edge remain
753    /// valid. However <tt>InEdge</tt>'s are invalidated.
[1909]754    void changeTarget(UEdge e, Node n) {
[2111]755      Parent::changeTarget(e,n);
[1718]756    }
757    /// Changes the source of \c e to \c n
758    ///
759    /// Changes the source of \c e to \c n
760    ///
761    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
762    ///referencing the changed edge remain
763    ///valid. However <tt>OutEdge</tt>'s are invalidated.
[1909]764    void changeSource(UEdge e, Node n) {
[2111]765      Parent::changeSource(e,n);
[1718]766    }
767    /// \brief Contract two nodes.
768    ///
769    /// This function contracts two nodes.
770    ///
771    /// Node \p b will be removed but instead of deleting
772    /// its neighboring edges, they will be joined to \p a.
773    /// The last parameter \p r controls whether to remove loops. \c true
774    /// means that loops will be removed.
775    ///
776    /// \note The <tt>Edge</tt>s
777    /// referencing a moved edge remain
778    /// valid.
779    void contract(Node a, Node b, bool r = true) {
780      for(IncEdgeIt e(*this, b); e!=INVALID;) {
781        IncEdgeIt f = e; ++f;
782        if (r && runningNode(e) == a) {
783          erase(e);
784        } else if (source(e) == b) {
785          changeSource(e, a);
786        } else {
787          changeTarget(e, a);
788        }
789        e = f;
790      }
791      erase(b);
792    }
[1034]793  };
794
[1982]795
796  class ListBpUGraphBase {
797  public:
798
799    class NodeSetError : public LogicError {
800      virtual const char* exceptionName() const {
801        return "lemon::ListBpUGraph::NodeSetError";
802      }
803    };
804
805  protected:
806
807    struct NodeT {
[2098]808      int first_edge, prev, next;
[1982]809    };
810
[2076]811    struct UEdgeT {
[1982]812      int aNode, prev_out, next_out;
813      int bNode, prev_in, next_in;
814    };
815
816    std::vector<NodeT> aNodes;
817    std::vector<NodeT> bNodes;
818
[2076]819    std::vector<UEdgeT> edges;
[1982]820
821    int first_anode;
822    int first_free_anode;
823
824    int first_bnode;
825    int first_free_bnode;
826
827    int first_free_edge;
828
829  public:
830 
831    class Node {
832      friend class ListBpUGraphBase;
833    protected:
834      int id;
835
[2031]836      explicit Node(int _id) : id(_id) {}
[1982]837    public:
838      Node() {}
839      Node(Invalid) { id = -1; }
840      bool operator==(const Node i) const {return id==i.id;}
841      bool operator!=(const Node i) const {return id!=i.id;}
842      bool operator<(const Node i) const {return id<i.id;}
843    };
844
[2076]845    class UEdge {
[1982]846      friend class ListBpUGraphBase;
847    protected:
848      int id;
849
[2076]850      explicit UEdge(int _id) { id = _id;}
[1982]851    public:
[2076]852      UEdge() {}
853      UEdge (Invalid) { id = -1; }
854      bool operator==(const UEdge i) const {return id==i.id;}
855      bool operator!=(const UEdge i) const {return id!=i.id;}
856      bool operator<(const UEdge i) const {return id<i.id;}
[1982]857    };
858
859    ListBpUGraphBase()
860      : first_anode(-1), first_free_anode(-1),
861        first_bnode(-1), first_free_bnode(-1),
862        first_free_edge(-1) {}
863
864    void firstANode(Node& node) const {
865      node.id = first_anode != -1 ? (first_anode << 1) : -1;
866    }
867    void nextANode(Node& node) const {
[2098]868      node.id = aNodes[node.id >> 1].next;
[1982]869    }
870
871    void firstBNode(Node& node) const {
[2098]872      node.id = first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
[1982]873    }
874    void nextBNode(Node& node) const {
[2098]875      node.id = bNodes[node.id >> 1].next;
[1982]876    }
877
878    void first(Node& node) const {
879      if (first_anode != -1) {
880        node.id = (first_anode << 1);
881      } else if (first_bnode != -1) {
882        node.id = (first_bnode << 1) + 1;
883      } else {
884        node.id = -1;
885      }
886    }
887    void next(Node& node) const {
888      if (aNode(node)) {
[2098]889        node.id = aNodes[node.id >> 1].next;
[1982]890        if (node.id == -1) {
891          if (first_bnode != -1) {
892            node.id = (first_bnode << 1) + 1;
893          }
894        }
895      } else {
[2098]896        node.id = bNodes[node.id >> 1].next;
[1982]897      }
898    }
899 
[2076]900    void first(UEdge& edge) const {
[1982]901      int aNodeId = first_anode;
902      while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
[2098]903        aNodeId = aNodes[aNodeId].next != -1 ?
904          aNodes[aNodeId].next >> 1 : -1;
[1982]905      }
906      if (aNodeId != -1) {
907        edge.id = aNodes[aNodeId].first_edge;
908      } else {
909        edge.id = -1;
910      }
911    }
[2076]912    void next(UEdge& edge) const {
[1982]913      int aNodeId = edges[edge.id].aNode >> 1;
914      edge.id = edges[edge.id].next_out;
915      if (edge.id == -1) {
[2098]916        aNodeId = aNodes[aNodeId].next != -1 ?
917          aNodes[aNodeId].next >> 1 : -1;
[1982]918        while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
[2098]919          aNodeId = aNodes[aNodeId].next != -1 ?
920          aNodes[aNodeId].next >> 1 : -1;
[1982]921        }
922        if (aNodeId != -1) {
923          edge.id = aNodes[aNodeId].first_edge;
924        } else {
925          edge.id = -1;
926        }
927      }
928    }
929
[2076]930    void firstFromANode(UEdge& edge, const Node& node) const {
[1982]931      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
932      edge.id = aNodes[node.id >> 1].first_edge;
933    }
[2076]934    void nextFromANode(UEdge& edge) const {
[1982]935      edge.id = edges[edge.id].next_out;
936    }
937
[2076]938    void firstFromBNode(UEdge& edge, const Node& node) const {
[1982]939      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
940      edge.id = bNodes[node.id >> 1].first_edge;
941    }
[2076]942    void nextFromBNode(UEdge& edge) const {
[1982]943      edge.id = edges[edge.id].next_in;
944    }
945
946    static int id(const Node& node) {
947      return node.id;
948    }
949    static Node nodeFromId(int id) {
950      return Node(id);
951    }
952    int maxNodeId() const {
953      return aNodes.size() > bNodes.size() ?
954        aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
955    }
956 
[2076]957    static int id(const UEdge& edge) {
[1982]958      return edge.id;
959    }
[2076]960    static UEdge uEdgeFromId(int id) {
961      return UEdge(id);
[1982]962    }
[2076]963    int maxUEdgeId() const {
[1982]964      return edges.size();
965    }
966 
967    static int aNodeId(const Node& node) {
968      return node.id >> 1;
969    }
[1995]970    static Node fromANodeId(int id) {
[1982]971      return Node(id << 1);
972    }
973    int maxANodeId() const {
974      return aNodes.size();
975    }
976
977    static int bNodeId(const Node& node) {
978      return node.id >> 1;
979    }
980    static Node fromBNodeId(int id) {
981      return Node((id << 1) + 1);
982    }
983    int maxBNodeId() const {
984      return bNodes.size();
985    }
986
[2076]987    Node aNode(const UEdge& edge) const {
[1982]988      return Node(edges[edge.id].aNode);
989    }
[2076]990    Node bNode(const UEdge& edge) const {
[1982]991      return Node(edges[edge.id].bNode);
992    }
993
994    static bool aNode(const Node& node) {
995      return (node.id & 1) == 0;
996    }
997
998    static bool bNode(const Node& node) {
999      return (node.id & 1) == 1;
1000    }
1001
1002    Node addANode() {
1003      int aNodeId;
1004      if (first_free_anode == -1) {
1005        aNodeId = aNodes.size();
1006        aNodes.push_back(NodeT());
1007      } else {
1008        aNodeId = first_free_anode;
[2098]1009        first_free_anode = aNodes[first_free_anode].next;
[1982]1010      }
[2098]1011      if (first_anode != -1) {
1012        aNodes[aNodeId].next = first_anode << 1;
1013        aNodes[first_anode].prev = aNodeId << 1;
1014      } else {
1015        aNodes[aNodeId].next = -1;
1016      }
1017      aNodes[aNodeId].prev = -1;
[1982]1018      first_anode = aNodeId;
1019      aNodes[aNodeId].first_edge = -1;
1020      return Node(aNodeId << 1);
1021    }
1022
1023    Node addBNode() {
1024      int bNodeId;
[1984]1025      if (first_free_bnode == -1) {
[1982]1026        bNodeId = bNodes.size();
1027        bNodes.push_back(NodeT());
1028      } else {
1029        bNodeId = first_free_bnode;
[2098]1030        first_free_bnode = bNodes[first_free_bnode].next;
[1982]1031      }
[2098]1032      if (first_bnode != -1) {
1033        bNodes[bNodeId].next = (first_bnode << 1) + 1;
1034        bNodes[first_bnode].prev = (bNodeId << 1) + 1;
1035      } else {
1036        bNodes[bNodeId].next = -1;
1037      }
[1982]1038      first_bnode = bNodeId;
1039      bNodes[bNodeId].first_edge = -1;
1040      return Node((bNodeId << 1) + 1);
1041    }
1042
[2076]1043    UEdge addEdge(const Node& source, const Node& target) {
[1982]1044      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
1045      int edgeId;
1046      if (first_free_edge != -1) {
1047        edgeId = first_free_edge;
1048        first_free_edge = edges[edgeId].next_out;
1049      } else {
1050        edgeId = edges.size();
[2076]1051        edges.push_back(UEdgeT());
[1982]1052      }
1053      if ((source.id & 1) == 0) {
1054        edges[edgeId].aNode = source.id;
1055        edges[edgeId].bNode = target.id;
1056      } else {
1057        edges[edgeId].aNode = target.id;
1058        edges[edgeId].bNode = source.id;
1059      }
1060      edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
1061      edges[edgeId].prev_out = -1;
1062      if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
1063        edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
1064      }
1065      aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
1066      edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
1067      edges[edgeId].prev_in = -1;
1068      if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
1069        edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
1070      }
1071      bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
[2076]1072      return UEdge(edgeId);
[1982]1073    }
1074
1075    void erase(const Node& node) {
1076      if (aNode(node)) {
1077        int aNodeId = node.id >> 1;
[2098]1078        if (aNodes[aNodeId].prev != -1) {
1079          aNodes[aNodes[aNodeId].prev >> 1].next = aNodes[aNodeId].next;
1080        } else {
1081          first_anode = aNodes[aNodeId].next >> 1;
1082        }
1083        if (aNodes[aNodeId].next != -1) {
1084          aNodes[aNodes[aNodeId].next >> 1].prev = aNodes[aNodeId].prev;
1085        }
1086        aNodes[aNodeId].next = first_free_anode;
[1982]1087        first_free_anode = aNodeId;
1088      } else {
1089        int bNodeId = node.id >> 1;
[2098]1090        if (bNodes[bNodeId].prev != -1) {
1091          bNodes[bNodes[bNodeId].prev >> 1].next = bNodes[bNodeId].next;
1092        } else {
1093          first_bnode = bNodes[bNodeId].next >> 1;
1094        }
1095        if (bNodes[bNodeId].next != -1) {
1096          bNodes[bNodes[bNodeId].next >> 1].prev = bNodes[bNodeId].prev;
1097        }
1098        bNodes[bNodeId].next = first_free_bnode;
[1982]1099        first_free_bnode = bNodeId;
1100      }
1101    }
1102
[2076]1103    void erase(const UEdge& edge) {
[2098]1104
[1982]1105      if (edges[edge.id].prev_out != -1) {
1106        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
1107      } else {
[2098]1108        aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;
[1982]1109      }
1110      if (edges[edge.id].next_out != -1) {
1111        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
1112      }
[2098]1113
[1982]1114      if (edges[edge.id].prev_in != -1) {
1115        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
1116      } else {
[2098]1117        bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;
[1982]1118      }
1119      if (edges[edge.id].next_in != -1) {
1120        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
1121      }
[2098]1122
[1982]1123      edges[edge.id].next_out = first_free_edge;
1124      first_free_edge = edge.id;
1125    }
1126
1127    void clear() {
1128      aNodes.clear();
1129      bNodes.clear();
1130      edges.clear();
1131      first_anode = -1;
1132      first_free_anode = -1;
1133      first_bnode = -1;
1134      first_free_bnode = -1;
1135      first_free_edge = -1;
1136    }
1137
1138  };
1139
1140
[2076]1141  typedef BpUGraphExtender< ListBpUGraphBase > ExtendedListBpUGraphBase;
[1982]1142
1143  /// \ingroup graphs
1144  ///
1145  /// \brief A smart bipartite undirected graph class.
1146  ///
1147  /// This is a bipartite undirected graph implementation.
[1991]1148  /// It is conforms to the \ref concept::ErasableBpUGraph "ErasableBpUGraph"
1149  /// concept.
[1982]1150  /// \sa concept::BpUGraph.
1151  ///
1152  class ListBpUGraph : public ExtendedListBpUGraphBase {};
1153
[949]1154 
[948]1155  /// @} 
1156} //namespace lemon
[946]1157 
[400]1158
[946]1159#endif
Note: See TracBrowser for help on using the repository browser.