COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2111:ea1fa1bc3f6d

Last change on this file since 2111:ea1fa1bc3f6d was 2111:ea1fa1bc3f6d, checked in by Balazs Dezso, 13 years ago

Removing concepts for extendable and erasable graphs
Renaming StaticGraph? to Graph

File size: 27.1 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    /// \warning It adds the new node to the front of the list.
170    /// (i.e. the lastly added node becomes the first.)
171    Node addNode() {     
172      int n;
173     
174      if(first_free_node==-1) {
175        n = nodes.size();
176        nodes.push_back(NodeT());
177      } else {
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     
189      return Node(n);
190    }
191   
192    Edge addEdge(Node u, Node v) {
193      int n;     
194
195      if (first_free_edge == -1) {
196        n = edges.size();
197        edges.push_back(EdgeT());
198      } else {
199        n = first_free_edge;
200        first_free_edge = edges[n].next_in;
201      }
202     
203      edges[n].source = u.id;
204      edges[n].target = v.id;
205
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     
216      edges[n].prev_in = edges[n].prev_out = -1;
217       
218      nodes[u.id].first_out = nodes[v.id].first_in = n;
219
220      return Edge(n);
221    }
222   
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;
238
239    }
240   
241    void erase(const Edge& edge) {
242      int n = edge.id;
243     
244      if(edges[n].next_in!=-1) {
245        edges[edges[n].next_in].prev_in = edges[n].prev_in;
246      }
247
248      if(edges[n].prev_in!=-1) {
249        edges[edges[n].prev_in].next_in = edges[n].next_in;
250      } else {
251        nodes[edges[n].target].first_in = edges[n].next_in;
252      }
253
254     
255      if(edges[n].next_out!=-1) {
256        edges[edges[n].next_out].prev_out = edges[n].prev_out;
257      }
258
259      if(edges[n].prev_out!=-1) {
260        edges[edges[n].prev_out].next_out = edges[n].next_out;
261      } else {
262        nodes[edges[n].source].first_out = edges[n].next_out;
263      }
264     
265      edges[n].next_in = first_free_edge;
266      first_free_edge = n;     
267
268    }
269
270    void clear() {
271      edges.clear();
272      nodes.clear();
273      first_node = first_free_node = first_free_edge = -1;
274    }
275
276  protected:
277    void changeTarget(Edge e, Node n)
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;
283      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
284      if (nodes[n.id].first_in != -1) {
285        edges[nodes[n.id].first_in].prev_in = e.id;
286      }
287      edges[e.id].target = n.id;
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    }
292    void changeSource(Edge e, Node n)
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;
298      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
299      if (nodes[n.id].first_out != -1) {
300        edges[nodes[n.id].first_out].prev_out = e.id;
301      }
302      edges[e.id].source = n.id;
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
308  };
309
310  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
311
312  /// \addtogroup graphs
313  /// @{
314
315  ///A list graph class.
316
317  ///This is a simple and fast erasable graph implementation.
318  ///
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.
324
325  class ListGraph : public ExtendedListGraphBase {
326  public:
327
328    typedef ExtendedListGraphBase Parent;
329
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
345    /// Changes the target of \c e to \c n
346
347    /// Changes the target of \c e to \c n
348    ///
349    ///\note The <tt>Edge</tt>s and <tt>OutEdge</tt>s
350    ///referencing the changed edge remain
351    ///valid. However <tt>InEdge</tt>s are invalidated.
352    void changeTarget(Edge e, Node n) {
353      Parent::changeTarget(e,n);
354    }
355    /// Changes the source of \c e to \c n
356
357    /// Changes the source of \c e to \c n
358    ///
359    ///\note The <tt>Edge</tt>s and <tt>InEdge</tt>s
360    ///referencing the changed edge remain
361    ///valid. However <tt>OutEdge</tt>s are invalidated.
362    void changeSource(Edge e, Node n) {
363      Parent::changeSource(e,n);
364    }
365
366    /// Invert the direction of an edge.
367
368    ///\note The <tt>Edge</tt>s
369    ///referencing the changed edge remain
370    ///valid. However <tt>OutEdge</tt>s  and <tt>InEdge</tt>s are invalidated.
371    void reverseEdge(Edge e) {
372      Node t=target(e);
373      changeTarget(e,source(e));
374      changeSource(e,t);
375    }
376
377    /// \brief Using this it is possible to avoid the superfluous memory
378    /// allocation.
379
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
386    /// \brief Using this it is possible to avoid the superfluous memory
387    /// allocation.
388
389    ///Using this it is possible to avoid the superfluous memory
390    ///allocation: see the \ref reserveNode function.
391    void reserveEdge(int n) { edges.reserve(n); };
392
393
394    ///Contract two nodes.
395
396    ///This function contracts two nodes.
397    ///
398    ///Node \p b will be removed but instead of deleting
399    ///incident edges, they will be joined to \p a.
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
404    ///referencing a moved edge remain
405    ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
406    ///may be invalidated.
407    void contract(Node a, Node b, bool r = true)
408    {
409      for(OutEdgeIt e(*this,b);e!=INVALID;) {
410        OutEdgeIt f=e;
411        ++f;
412        if(r && target(e)==a) erase(e);
413        else changeSource(e,a);
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);
420        else changeTarget(e,a);
421        e=f;
422      }
423      erase(b);
424    }
425
426    ///Split a node.
427
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.
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
436    ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
437    ///may be invalidated.
438    ///\warning This functionality cannot be used together with the Snapshot
439    ///feature.
440    ///\todo It could be implemented in a bit faster way.
441    Node split(Node n, bool connect = true)
442    {
443      Node b = addNode();
444      for(OutEdgeIt e(*this,n);e!=INVALID;) {
445        OutEdgeIt f=e;
446        ++f;
447        changeSource(e,b);
448        e=f;
449      }
450      if(connect) addEdge(n,b);
451      return b;
452    }
453     
454    ///Split an edge.
455
456    ///This function splits an edge. First a new node \c b is added to
457    ///the graph, then the original edge is re-targeted to \c
458    ///b. Finally an edge from \c b to the original target is added.
459    ///\return The newly created node. 
460    ///\warning This functionality
461    ///cannot be used together with the Snapshot feature.
462    Node split(Edge e)
463    {
464      Node b = addNode();
465      addEdge(b,target(e));
466      changeTarget(e,b);
467      return b;
468    }
469     
470    ///Class to make a snapshot of the graph and to restore  it later.
471
472    ///Class to make a snapshot of the graph and to restore  it later.
473    ///
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    ///\warning Snapshots cannot be nested.
479    class Snapshot : protected Parent::NodeNotifier::ObserverBase,
480                     protected Parent::EdgeNotifier::ObserverBase
481    {
482    public:
483     
484      class UnsupportedOperation : public LogicError {
485      public:
486        virtual const char* exceptionName() const {
487          return "lemon::ListGraph::Snapshot::UnsupportedOperation";
488        }
489      };
490           
491
492    protected:
493     
494      ListGraph *g;
495      std::list<Node> added_nodes;
496      std::list<Edge> added_edges;
497     
498      bool active;
499      virtual void add(const Node& n) {
500        added_nodes.push_back(n);
501      };
502      virtual void erase(const Node&)
503      {
504        throw UnsupportedOperation();
505      }
506      virtual void add(const Edge& n) {
507        added_edges.push_back(n);
508      };
509      virtual void erase(const Edge&)
510      {
511        throw UnsupportedOperation();
512      }
513
514      ///\bug What is this used for?
515      ///
516      virtual void build() {}
517      ///\bug What is this used for?
518      ///
519      virtual void clear() {}
520
521      void regist(ListGraph &_g) {
522        g=&_g;
523        Parent::NodeNotifier::ObserverBase::attach(g->getNotifier(Node()));
524        Parent::EdgeNotifier::ObserverBase::attach(g->getNotifier(Edge()));
525      }
526           
527      void deregist() {
528        Parent::NodeNotifier::ObserverBase::detach();
529        Parent::EdgeNotifier::ObserverBase::detach();
530        g=0;
531      }
532
533    public:
534      ///Default constructur.
535     
536      ///Default constructur.
537      ///To actually make a snapshot you must call save().
538      ///
539      Snapshot() : g(0) {}
540      ///Constructor that immediately makes a snapshot.
541     
542      ///This constructor immediately makes a snapshot of the graph.
543      ///\param _g The graph we make a snapshot of.
544      Snapshot(ListGraph &_g) {
545        regist(_g);
546      }
547      ///\bug Is it necessary?
548      ///
549      ~Snapshot()
550      {
551        if(g) deregist();
552      }
553     
554      ///Make a snapshot.
555
556      ///Make a snapshot of the graph.
557      ///
558      ///This function can be called more than once. In case of a repeated
559      ///call, the previous snapshot gets lost.
560      ///\param _g The graph we make the snapshot of.
561      void save(ListGraph &_g)
562      {
563        if(g!=&_g) {
564          if(g) deregist();
565          regist(_g);
566        }
567        added_nodes.clear();
568        added_edges.clear();
569      }
570     
571    ///Undo the changes until the last snapshot.
572
573    ///Undo the changes until last snapshot created by save().
574    ///
575    ///\todo This function might be called undo().
576      void restore() {
577        ListGraph &old_g=*g;
578        deregist();
579        while(!added_edges.empty()) {
580          old_g.erase(added_edges.front());
581          added_edges.pop_front();
582        }
583        while(!added_nodes.empty()) {
584          old_g.erase(added_nodes.front());
585          added_nodes.pop_front();
586        }
587      }
588    };
589   
590  };
591
592  ///@}
593
594  /**************** Undirected List Graph ****************/
595
596  typedef UGraphExtender<UndirGraphExtender<ListGraphBase> >
597  ExtendedListUGraphBase;
598
599  /// \addtogroup graphs
600  /// @{
601
602  ///An undirected list graph class.
603
604  ///This is a simple and fast erasable undirected graph implementation.
605  ///
606  ///It conforms to the
607  ///\ref concept::UGraph "UGraph" concept.
608  ///
609  ///\sa concept::UGraph.
610  ///
611  ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
612  ///haven't been implemented yet.
613  ///
614  class ListUGraph : public ExtendedListUGraphBase {
615  public:
616    typedef ExtendedListUGraphBase Parent;
617    /// \brief Add a new node to the graph.
618    ///
619    /// \return the new node.
620    ///
621    Node addNode() { return Parent::addNode(); }
622
623    /// \brief Add a new edge to the graph.
624    ///
625    /// Add a new edge to the graph with source node \c s
626    /// and target node \c t.
627    /// \return the new undirected edge.
628    UEdge addEdge(const Node& s, const Node& t) {
629      return Parent::addEdge(s, t);
630    }
631    /// \brief Changes the target of \c e to \c n
632    ///
633    /// Changes the target of \c e to \c n
634    ///
635    /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
636    /// referencing the changed edge remain
637    /// valid. However <tt>InEdge</tt>'s are invalidated.
638    void changeTarget(UEdge e, Node n) {
639      Parent::changeTarget(e,n);
640    }
641    /// Changes the source of \c e to \c n
642    ///
643    /// Changes the source of \c e to \c n
644    ///
645    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
646    ///referencing the changed edge remain
647    ///valid. However <tt>OutEdge</tt>'s are invalidated.
648    void changeSource(UEdge e, Node n) {
649      Parent::changeSource(e,n);
650    }
651    /// \brief Contract two nodes.
652    ///
653    /// This function contracts two nodes.
654    ///
655    /// Node \p b will be removed but instead of deleting
656    /// its neighboring edges, they will be joined to \p a.
657    /// The last parameter \p r controls whether to remove loops. \c true
658    /// means that loops will be removed.
659    ///
660    /// \note The <tt>Edge</tt>s
661    /// referencing a moved edge remain
662    /// valid.
663    void contract(Node a, Node b, bool r = true) {
664      for(IncEdgeIt e(*this, b); e!=INVALID;) {
665        IncEdgeIt f = e; ++f;
666        if (r && runningNode(e) == a) {
667          erase(e);
668        } else if (source(e) == b) {
669          changeSource(e, a);
670        } else {
671          changeTarget(e, a);
672        }
673        e = f;
674      }
675      erase(b);
676    }
677  };
678
679
680  class ListBpUGraphBase {
681  public:
682
683    class NodeSetError : public LogicError {
684      virtual const char* exceptionName() const {
685        return "lemon::ListBpUGraph::NodeSetError";
686      }
687    };
688
689  protected:
690
691    struct NodeT {
692      int first_edge, prev, next;
693    };
694
695    struct UEdgeT {
696      int aNode, prev_out, next_out;
697      int bNode, prev_in, next_in;
698    };
699
700    std::vector<NodeT> aNodes;
701    std::vector<NodeT> bNodes;
702
703    std::vector<UEdgeT> edges;
704
705    int first_anode;
706    int first_free_anode;
707
708    int first_bnode;
709    int first_free_bnode;
710
711    int first_free_edge;
712
713  public:
714 
715    class Node {
716      friend class ListBpUGraphBase;
717    protected:
718      int id;
719
720      explicit Node(int _id) : id(_id) {}
721    public:
722      Node() {}
723      Node(Invalid) { id = -1; }
724      bool operator==(const Node i) const {return id==i.id;}
725      bool operator!=(const Node i) const {return id!=i.id;}
726      bool operator<(const Node i) const {return id<i.id;}
727    };
728
729    class UEdge {
730      friend class ListBpUGraphBase;
731    protected:
732      int id;
733
734      explicit UEdge(int _id) { id = _id;}
735    public:
736      UEdge() {}
737      UEdge (Invalid) { id = -1; }
738      bool operator==(const UEdge i) const {return id==i.id;}
739      bool operator!=(const UEdge i) const {return id!=i.id;}
740      bool operator<(const UEdge i) const {return id<i.id;}
741    };
742
743    ListBpUGraphBase()
744      : first_anode(-1), first_free_anode(-1),
745        first_bnode(-1), first_free_bnode(-1),
746        first_free_edge(-1) {}
747
748    void firstANode(Node& node) const {
749      node.id = first_anode != -1 ? (first_anode << 1) : -1;
750    }
751    void nextANode(Node& node) const {
752      node.id = aNodes[node.id >> 1].next;
753    }
754
755    void firstBNode(Node& node) const {
756      node.id = first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
757    }
758    void nextBNode(Node& node) const {
759      node.id = bNodes[node.id >> 1].next;
760    }
761
762    void first(Node& node) const {
763      if (first_anode != -1) {
764        node.id = (first_anode << 1);
765      } else if (first_bnode != -1) {
766        node.id = (first_bnode << 1) + 1;
767      } else {
768        node.id = -1;
769      }
770    }
771    void next(Node& node) const {
772      if (aNode(node)) {
773        node.id = aNodes[node.id >> 1].next;
774        if (node.id == -1) {
775          if (first_bnode != -1) {
776            node.id = (first_bnode << 1) + 1;
777          }
778        }
779      } else {
780        node.id = bNodes[node.id >> 1].next;
781      }
782    }
783 
784    void first(UEdge& edge) const {
785      int aNodeId = first_anode;
786      while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
787        aNodeId = aNodes[aNodeId].next != -1 ?
788          aNodes[aNodeId].next >> 1 : -1;
789      }
790      if (aNodeId != -1) {
791        edge.id = aNodes[aNodeId].first_edge;
792      } else {
793        edge.id = -1;
794      }
795    }
796    void next(UEdge& edge) const {
797      int aNodeId = edges[edge.id].aNode >> 1;
798      edge.id = edges[edge.id].next_out;
799      if (edge.id == -1) {
800        aNodeId = aNodes[aNodeId].next != -1 ?
801          aNodes[aNodeId].next >> 1 : -1;
802        while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
803          aNodeId = aNodes[aNodeId].next != -1 ?
804          aNodes[aNodeId].next >> 1 : -1;
805        }
806        if (aNodeId != -1) {
807          edge.id = aNodes[aNodeId].first_edge;
808        } else {
809          edge.id = -1;
810        }
811      }
812    }
813
814    void firstFromANode(UEdge& edge, const Node& node) const {
815      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
816      edge.id = aNodes[node.id >> 1].first_edge;
817    }
818    void nextFromANode(UEdge& edge) const {
819      edge.id = edges[edge.id].next_out;
820    }
821
822    void firstFromBNode(UEdge& edge, const Node& node) const {
823      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
824      edge.id = bNodes[node.id >> 1].first_edge;
825    }
826    void nextFromBNode(UEdge& edge) const {
827      edge.id = edges[edge.id].next_in;
828    }
829
830    static int id(const Node& node) {
831      return node.id;
832    }
833    static Node nodeFromId(int id) {
834      return Node(id);
835    }
836    int maxNodeId() const {
837      return aNodes.size() > bNodes.size() ?
838        aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
839    }
840 
841    static int id(const UEdge& edge) {
842      return edge.id;
843    }
844    static UEdge uEdgeFromId(int id) {
845      return UEdge(id);
846    }
847    int maxUEdgeId() const {
848      return edges.size();
849    }
850 
851    static int aNodeId(const Node& node) {
852      return node.id >> 1;
853    }
854    static Node fromANodeId(int id) {
855      return Node(id << 1);
856    }
857    int maxANodeId() const {
858      return aNodes.size();
859    }
860
861    static int bNodeId(const Node& node) {
862      return node.id >> 1;
863    }
864    static Node fromBNodeId(int id) {
865      return Node((id << 1) + 1);
866    }
867    int maxBNodeId() const {
868      return bNodes.size();
869    }
870
871    Node aNode(const UEdge& edge) const {
872      return Node(edges[edge.id].aNode);
873    }
874    Node bNode(const UEdge& edge) const {
875      return Node(edges[edge.id].bNode);
876    }
877
878    static bool aNode(const Node& node) {
879      return (node.id & 1) == 0;
880    }
881
882    static bool bNode(const Node& node) {
883      return (node.id & 1) == 1;
884    }
885
886    Node addANode() {
887      int aNodeId;
888      if (first_free_anode == -1) {
889        aNodeId = aNodes.size();
890        aNodes.push_back(NodeT());
891      } else {
892        aNodeId = first_free_anode;
893        first_free_anode = aNodes[first_free_anode].next;
894      }
895      if (first_anode != -1) {
896        aNodes[aNodeId].next = first_anode << 1;
897        aNodes[first_anode].prev = aNodeId << 1;
898      } else {
899        aNodes[aNodeId].next = -1;
900      }
901      aNodes[aNodeId].prev = -1;
902      first_anode = aNodeId;
903      aNodes[aNodeId].first_edge = -1;
904      return Node(aNodeId << 1);
905    }
906
907    Node addBNode() {
908      int bNodeId;
909      if (first_free_bnode == -1) {
910        bNodeId = bNodes.size();
911        bNodes.push_back(NodeT());
912      } else {
913        bNodeId = first_free_bnode;
914        first_free_bnode = bNodes[first_free_bnode].next;
915      }
916      if (first_bnode != -1) {
917        bNodes[bNodeId].next = (first_bnode << 1) + 1;
918        bNodes[first_bnode].prev = (bNodeId << 1) + 1;
919      } else {
920        bNodes[bNodeId].next = -1;
921      }
922      first_bnode = bNodeId;
923      bNodes[bNodeId].first_edge = -1;
924      return Node((bNodeId << 1) + 1);
925    }
926
927    UEdge addEdge(const Node& source, const Node& target) {
928      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
929      int edgeId;
930      if (first_free_edge != -1) {
931        edgeId = first_free_edge;
932        first_free_edge = edges[edgeId].next_out;
933      } else {
934        edgeId = edges.size();
935        edges.push_back(UEdgeT());
936      }
937      if ((source.id & 1) == 0) {
938        edges[edgeId].aNode = source.id;
939        edges[edgeId].bNode = target.id;
940      } else {
941        edges[edgeId].aNode = target.id;
942        edges[edgeId].bNode = source.id;
943      }
944      edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
945      edges[edgeId].prev_out = -1;
946      if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
947        edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
948      }
949      aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
950      edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
951      edges[edgeId].prev_in = -1;
952      if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
953        edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
954      }
955      bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
956      return UEdge(edgeId);
957    }
958
959    void erase(const Node& node) {
960      if (aNode(node)) {
961        int aNodeId = node.id >> 1;
962        if (aNodes[aNodeId].prev != -1) {
963          aNodes[aNodes[aNodeId].prev >> 1].next = aNodes[aNodeId].next;
964        } else {
965          first_anode = aNodes[aNodeId].next >> 1;
966        }
967        if (aNodes[aNodeId].next != -1) {
968          aNodes[aNodes[aNodeId].next >> 1].prev = aNodes[aNodeId].prev;
969        }
970        aNodes[aNodeId].next = first_free_anode;
971        first_free_anode = aNodeId;
972      } else {
973        int bNodeId = node.id >> 1;
974        if (bNodes[bNodeId].prev != -1) {
975          bNodes[bNodes[bNodeId].prev >> 1].next = bNodes[bNodeId].next;
976        } else {
977          first_bnode = bNodes[bNodeId].next >> 1;
978        }
979        if (bNodes[bNodeId].next != -1) {
980          bNodes[bNodes[bNodeId].next >> 1].prev = bNodes[bNodeId].prev;
981        }
982        bNodes[bNodeId].next = first_free_bnode;
983        first_free_bnode = bNodeId;
984      }
985    }
986
987    void erase(const UEdge& edge) {
988
989      if (edges[edge.id].prev_out != -1) {
990        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
991      } else {
992        aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;
993      }
994      if (edges[edge.id].next_out != -1) {
995        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
996      }
997
998      if (edges[edge.id].prev_in != -1) {
999        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
1000      } else {
1001        bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;
1002      }
1003      if (edges[edge.id].next_in != -1) {
1004        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
1005      }
1006
1007      edges[edge.id].next_out = first_free_edge;
1008      first_free_edge = edge.id;
1009    }
1010
1011    void clear() {
1012      aNodes.clear();
1013      bNodes.clear();
1014      edges.clear();
1015      first_anode = -1;
1016      first_free_anode = -1;
1017      first_bnode = -1;
1018      first_free_bnode = -1;
1019      first_free_edge = -1;
1020    }
1021
1022  };
1023
1024
1025  typedef BpUGraphExtender< ListBpUGraphBase > ExtendedListBpUGraphBase;
1026
1027  /// \ingroup graphs
1028  ///
1029  /// \brief A smart bipartite undirected graph class.
1030  ///
1031  /// This is a bipartite undirected graph implementation.
1032  /// It is conforms to the \ref concept::ErasableBpUGraph "ErasableBpUGraph"
1033  /// concept.
1034  /// \sa concept::BpUGraph.
1035  ///
1036  class ListBpUGraph : public ExtendedListBpUGraphBase {};
1037
1038 
1039  /// @} 
1040} //namespace lemon
1041 
1042
1043#endif
Note: See TracBrowser for help on using the repository browser.