COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2128:509846825ddf

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