COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2107:e1055232c670

Last change on this file since 2107:e1055232c670 was 2107:e1055232c670, checked in by Balazs Dezso, 18 years ago

Added reserveNode function.

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