COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2123:85c6f5e82108

Last change on this file since 2123:85c6f5e82108 was 2123:85c6f5e82108, checked in by Alpar Juttner, 13 years ago

Minor doc improvements

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