COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2037:32e4bebee616

Last change on this file since 2037:32e4bebee616 was 2031:080d51024ac5, checked in by Balazs Dezso, 18 years ago

Correcting the structure of the graph's and adaptor's map.
The template assign operators and map iterators can be used for adaptors also.

Some bugfix in the adaptors

New class SwapBpUGraphAdaptor which swaps the two nodeset of the graph.

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