lemon/list_graph.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1791 62e7d237e1fb
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
alpar@948
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/list_graph.h - Part of LEMON, a generic C++ optimization library
alpar@948
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@948
     6
 *
alpar@948
     7
 * Permission to use, modify and distribute this software is granted
alpar@948
     8
 * provided that this copyright notice appears in all copies. For
alpar@948
     9
 * precise terms see the accompanying LICENSE file.
alpar@948
    10
 *
alpar@948
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@948
    12
 * express or implied, and with no claim as to its suitability for any
alpar@948
    13
 * purpose.
alpar@948
    14
 *
alpar@948
    15
 */
alpar@395
    16
alpar@921
    17
#ifndef LEMON_LIST_GRAPH_H
alpar@921
    18
#define LEMON_LIST_GRAPH_H
alpar@395
    19
alpar@948
    20
///\ingroup graphs
alpar@948
    21
///\file
deba@1692
    22
///\brief ListGraph, UndirListGraph classes.
alpar@948
    23
deba@1307
    24
#include <lemon/bits/erasable_graph_extender.h>
deba@1307
    25
#include <lemon/bits/clearable_graph_extender.h>
deba@1307
    26
#include <lemon/bits/extendable_graph_extender.h>
deba@1307
    27
#include <lemon/bits/iterable_graph_extender.h>
deba@1307
    28
#include <lemon/bits/alteration_notifier.h>
deba@1307
    29
#include <lemon/bits/default_map.h>
deba@1791
    30
#include <lemon/bits/graph_extender.h>
deba@782
    31
deba@1774
    32
#include <lemon/error.h>
deba@1774
    33
alpar@1011
    34
#include <list>
deba@782
    35
alpar@921
    36
namespace lemon {
alpar@395
    37
klao@946
    38
  class ListGraphBase {
alpar@406
    39
alpar@949
    40
  protected:
klao@946
    41
    struct NodeT {
deba@1470
    42
      int first_in, first_out;
alpar@397
    43
      int prev, next;
alpar@395
    44
    };
klao@946
    45
 
klao@946
    46
    struct EdgeT {
alpar@986
    47
      int target, source;
alpar@397
    48
      int prev_in, prev_out;
alpar@397
    49
      int next_in, next_out;
alpar@395
    50
    };
alpar@395
    51
alpar@395
    52
    std::vector<NodeT> nodes;
klao@946
    53
alpar@397
    54
    int first_node;
klao@946
    55
alpar@397
    56
    int first_free_node;
klao@946
    57
alpar@395
    58
    std::vector<EdgeT> edges;
klao@946
    59
alpar@397
    60
    int first_free_edge;
alpar@395
    61
    
deba@782
    62
  public:
alpar@395
    63
    
klao@946
    64
    typedef ListGraphBase Graph;
alpar@397
    65
    
klao@946
    66
    class Node {
marci@975
    67
      friend class ListGraphBase;
klao@946
    68
    protected:
alpar@395
    69
klao@946
    70
      int id;
klao@946
    71
      Node(int pid) { id = pid;}
alpar@395
    72
klao@946
    73
    public:
klao@946
    74
      Node() {}
klao@946
    75
      Node (Invalid) { id = -1; }
klao@946
    76
      bool operator==(const Node& node) const {return id == node.id;}
klao@946
    77
      bool operator!=(const Node& node) const {return id != node.id;}
klao@946
    78
      bool operator<(const Node& node) const {return id < node.id;}
klao@946
    79
    };
deba@782
    80
klao@946
    81
    class Edge {
marci@975
    82
      friend class ListGraphBase;
klao@946
    83
    protected:
deba@782
    84
klao@946
    85
      int id;
klao@946
    86
      Edge(int pid) { id = pid;}
alpar@395
    87
klao@946
    88
    public:
klao@946
    89
      Edge() {}
klao@946
    90
      Edge (Invalid) { id = -1; }
klao@946
    91
      bool operator==(const Edge& edge) const {return id == edge.id;}
klao@946
    92
      bool operator!=(const Edge& edge) const {return id != edge.id;}
klao@946
    93
      bool operator<(const Edge& edge) const {return id < edge.id;}
klao@946
    94
    };
klao@946
    95
klao@946
    96
klao@946
    97
klao@946
    98
    ListGraphBase()
deba@782
    99
      : nodes(), first_node(-1),
deba@782
   100
	first_free_node(-1), edges(), first_free_edge(-1) {}
deba@782
   101
alpar@395
   102
    
alpar@813
   103
    /// Maximum node ID.
alpar@813
   104
    
alpar@813
   105
    /// Maximum node ID.
alpar@813
   106
    ///\sa id(Node)
deba@1791
   107
    int maxNodeId() const { return nodes.size()-1; } 
klao@946
   108
alpar@813
   109
    /// Maximum edge ID.
alpar@813
   110
    
alpar@813
   111
    /// Maximum edge ID.
alpar@813
   112
    ///\sa id(Edge)
deba@1791
   113
    int maxEdgeId() const { return edges.size()-1; }
alpar@395
   114
alpar@986
   115
    Node source(Edge e) const { return edges[e.id].source; }
alpar@986
   116
    Node target(Edge e) const { return edges[e.id].target; }
alpar@395
   117
alpar@395
   118
klao@946
   119
    void first(Node& node) const { 
klao@946
   120
      node.id = first_node;
klao@946
   121
    }
klao@946
   122
klao@946
   123
    void next(Node& node) const {
klao@946
   124
      node.id = nodes[node.id].next;
klao@946
   125
    }
klao@946
   126
klao@946
   127
klao@946
   128
    void first(Edge& e) const { 
klao@946
   129
      int n;
klao@946
   130
      for(n = first_node; 
klao@946
   131
	  n!=-1 && nodes[n].first_in == -1; 
klao@946
   132
	  n = nodes[n].next);
klao@946
   133
      e.id = (n == -1) ? -1 : nodes[n].first_in;
klao@946
   134
    }
klao@946
   135
klao@946
   136
    void next(Edge& edge) const {
klao@946
   137
      if (edges[edge.id].next_in != -1) {
klao@946
   138
	edge.id = edges[edge.id].next_in;
klao@946
   139
      } else {
klao@946
   140
	int n;
alpar@986
   141
	for(n = nodes[edges[edge.id].target].next;
klao@946
   142
	  n!=-1 && nodes[n].first_in == -1; 
klao@946
   143
	  n = nodes[n].next);
klao@946
   144
	edge.id = (n == -1) ? -1 : nodes[n].first_in;
klao@946
   145
      }      
klao@946
   146
    }
klao@946
   147
klao@946
   148
    void firstOut(Edge &e, const Node& v) const {
klao@946
   149
      e.id = nodes[v.id].first_out;
klao@946
   150
    }
klao@946
   151
    void nextOut(Edge &e) const {
klao@946
   152
      e.id=edges[e.id].next_out;
klao@946
   153
    }
klao@946
   154
klao@946
   155
    void firstIn(Edge &e, const Node& v) const {
klao@946
   156
      e.id = nodes[v.id].first_in;
klao@946
   157
    }
klao@946
   158
    void nextIn(Edge &e) const {
klao@946
   159
      e.id=edges[e.id].next_in;
klao@946
   160
    }
klao@946
   161
alpar@813
   162
    
klao@946
   163
    static int id(Node v) { return v.id; }
klao@946
   164
    static int id(Edge e) { return e.id; }
alpar@395
   165
deba@1791
   166
    static Node nodeFromId(int id) { return Node(id);}
deba@1791
   167
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   168
alpar@397
   169
    /// Adds a new node to the graph.
alpar@397
   170
alpar@813
   171
    /// \warning It adds the new node to the front of the list.
alpar@397
   172
    /// (i.e. the lastly added node becomes the first.)
klao@946
   173
    Node addNode() {     
alpar@397
   174
      int n;
alpar@397
   175
      
klao@946
   176
      if(first_free_node==-1) {
klao@946
   177
	n = nodes.size();
klao@946
   178
	nodes.push_back(NodeT());
klao@946
   179
      } else {
alpar@397
   180
	n = first_free_node;
alpar@397
   181
	first_free_node = nodes[n].next;
alpar@397
   182
      }
alpar@397
   183
      
alpar@397
   184
      nodes[n].next = first_node;
alpar@397
   185
      if(first_node != -1) nodes[first_node].prev = n;
alpar@397
   186
      first_node = n;
alpar@397
   187
      nodes[n].prev = -1;
alpar@397
   188
      
alpar@397
   189
      nodes[n].first_in = nodes[n].first_out = -1;
alpar@397
   190
      
klao@946
   191
      return Node(n);
alpar@395
   192
    }
alpar@395
   193
    
alpar@395
   194
    Edge addEdge(Node u, Node v) {
klao@946
   195
      int n;      
klao@946
   196
klao@946
   197
      if (first_free_edge == -1) {
klao@946
   198
	n = edges.size();
klao@946
   199
	edges.push_back(EdgeT());
klao@946
   200
      } else {
alpar@397
   201
	n = first_free_edge;
alpar@397
   202
	first_free_edge = edges[n].next_in;
alpar@397
   203
      }
alpar@397
   204
      
alpar@986
   205
      edges[n].source = u.id; 
alpar@986
   206
      edges[n].target = v.id;
alpar@395
   207
klao@946
   208
      edges[n].next_out = nodes[u.id].first_out;
klao@946
   209
      if(nodes[u.id].first_out != -1) {
klao@946
   210
	edges[nodes[u.id].first_out].prev_out = n;
klao@946
   211
      }
klao@946
   212
      
klao@946
   213
      edges[n].next_in = nodes[v.id].first_in;
klao@946
   214
      if(nodes[v.id].first_in != -1) {
klao@946
   215
	edges[nodes[v.id].first_in].prev_in = n;
klao@946
   216
      }
klao@946
   217
      
alpar@397
   218
      edges[n].prev_in = edges[n].prev_out = -1;
alpar@397
   219
	
klao@946
   220
      nodes[u.id].first_out = nodes[v.id].first_in = n;
alpar@397
   221
klao@946
   222
      return Edge(n);
alpar@395
   223
    }
alpar@774
   224
    
klao@946
   225
    void erase(const Node& node) {
klao@946
   226
      int n = node.id;
klao@946
   227
      
klao@946
   228
      if(nodes[n].next != -1) {
klao@946
   229
	nodes[nodes[n].next].prev = nodes[n].prev;
klao@946
   230
      }
klao@946
   231
      
klao@946
   232
      if(nodes[n].prev != -1) {
klao@946
   233
	nodes[nodes[n].prev].next = nodes[n].next;
klao@946
   234
      } else {
klao@946
   235
	first_node = nodes[n].next;
klao@946
   236
      }
klao@946
   237
      
klao@946
   238
      nodes[n].next = first_free_node;
klao@946
   239
      first_free_node = n;
alpar@395
   240
alpar@774
   241
    }
alpar@774
   242
    
klao@946
   243
    void erase(const Edge& edge) {
klao@946
   244
      int n = edge.id;
alpar@397
   245
      
klao@946
   246
      if(edges[n].next_in!=-1) {
alpar@397
   247
	edges[edges[n].next_in].prev_in = edges[n].prev_in;
klao@946
   248
      }
klao@946
   249
klao@946
   250
      if(edges[n].prev_in!=-1) {
alpar@397
   251
	edges[edges[n].prev_in].next_in = edges[n].next_in;
klao@946
   252
      } else {
alpar@986
   253
	nodes[edges[n].target].first_in = edges[n].next_in;
klao@946
   254
      }
klao@946
   255
alpar@397
   256
      
klao@946
   257
      if(edges[n].next_out!=-1) {
alpar@397
   258
	edges[edges[n].next_out].prev_out = edges[n].prev_out;
klao@946
   259
      } 
klao@946
   260
klao@946
   261
      if(edges[n].prev_out!=-1) {
alpar@397
   262
	edges[edges[n].prev_out].next_out = edges[n].next_out;
klao@946
   263
      } else {
alpar@986
   264
	nodes[edges[n].source].first_out = edges[n].next_out;
klao@946
   265
      }
alpar@397
   266
      
alpar@397
   267
      edges[n].next_in = first_free_edge;
alpar@695
   268
      first_free_edge = n;      
alpar@397
   269
alpar@397
   270
    }
alpar@397
   271
alpar@397
   272
    void clear() {
deba@782
   273
      edges.clear();
deba@782
   274
      nodes.clear();
klao@946
   275
      first_node = first_free_node = first_free_edge = -1;
deba@937
   276
    }
deba@937
   277
alpar@949
   278
  protected:
alpar@1546
   279
    void _changeTarget(Edge e, Node n) 
alpar@949
   280
    {
alpar@949
   281
      if(edges[e.id].next_in != -1)
alpar@949
   282
	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
alpar@949
   283
      if(edges[e.id].prev_in != -1)
alpar@949
   284
	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
alpar@986
   285
      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
deba@1702
   286
      if (nodes[n.id].first_in != -1) {
deba@1702
   287
	edges[nodes[n.id].first_in].prev_in = e.id;
deba@1702
   288
      }
alpar@986
   289
      edges[e.id].target = n.id;
alpar@949
   290
      edges[e.id].prev_in = -1;
alpar@949
   291
      edges[e.id].next_in = nodes[n.id].first_in;
alpar@949
   292
      nodes[n.id].first_in = e.id;
alpar@949
   293
    }
alpar@1546
   294
    void _changeSource(Edge e, Node n) 
alpar@949
   295
    {
alpar@949
   296
      if(edges[e.id].next_out != -1)
alpar@949
   297
	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
alpar@949
   298
      if(edges[e.id].prev_out != -1)
alpar@949
   299
	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
alpar@986
   300
      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
deba@1702
   301
      if (nodes[n.id].first_out != -1) {
deba@1702
   302
	edges[nodes[n.id].first_out].prev_out = e.id;
deba@1702
   303
      }
alpar@986
   304
      edges[e.id].source = n.id;
alpar@949
   305
      edges[e.id].prev_out = -1;
alpar@949
   306
      edges[e.id].next_out = nodes[n.id].first_out;
alpar@949
   307
      nodes[n.id].first_out = e.id;
alpar@949
   308
    }
alpar@949
   309
alpar@919
   310
  };
deba@909
   311
deba@1669
   312
  typedef ErasableGraphExtender<
deba@1669
   313
    ClearableGraphExtender<
deba@1669
   314
    ExtendableGraphExtender<
deba@1669
   315
    MappableGraphExtender<
deba@1669
   316
    IterableGraphExtender<
deba@1791
   317
    AlterableGraphExtender<
deba@1791
   318
    GraphExtender<ListGraphBase> > > > > > > ExtendedListGraphBase;
alpar@400
   319
deba@1718
   320
  /// \addtogroup graphs
deba@1718
   321
  /// @{
alpar@400
   322
alpar@948
   323
  ///A list graph class.
alpar@400
   324
alpar@948
   325
  ///This is a simple and fast erasable graph implementation.
alpar@948
   326
  ///
alpar@1010
   327
  ///It addition that it conforms to the
alpar@1010
   328
  ///\ref concept::ErasableGraph "ErasableGraph" concept,
alpar@1010
   329
  ///it also provides several additional useful extra functionalities.
klao@959
   330
  ///\sa concept::ErasableGraph.
deba@782
   331
deba@1669
   332
  class ListGraph : public ExtendedListGraphBase 
alpar@948
   333
  {
alpar@948
   334
  public:
alpar@1546
   335
    /// Changes the target of \c e to \c n
alpar@948
   336
alpar@1546
   337
    /// Changes the target of \c e to \c n
alpar@948
   338
    ///
alpar@1010
   339
    ///\note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
alpar@1546
   340
    ///referencing the changed edge remain
alpar@1010
   341
    ///valid. However <tt>InEdge</tt>'s are invalidated.
deba@1718
   342
    void changeTarget(Edge e, Node n) { 
deba@1718
   343
      _changeTarget(e,n); 
deba@1718
   344
    }
alpar@1546
   345
    /// Changes the source of \c e to \c n
alpar@948
   346
alpar@1546
   347
    /// Changes the source of \c e to \c n
alpar@948
   348
    ///
alpar@1010
   349
    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
alpar@1546
   350
    ///referencing the changed edge remain
alpar@1010
   351
    ///valid. However <tt>OutEdge</tt>'s are invalidated.
deba@1718
   352
    void changeSource(Edge e, Node n) { 
deba@1718
   353
      _changeSource(e,n);
deba@1718
   354
    }
alpar@949
   355
alpar@1010
   356
    /// Invert the direction of an edge.
alpar@1010
   357
alpar@1010
   358
    ///\note The <tt>Edge</tt>'s
alpar@1546
   359
    ///referencing the changed edge remain
alpar@1010
   360
    ///valid. However <tt>OutEdge</tt>'s  and <tt>InEdge</tt>'s are invalidated.
alpar@1010
   361
    void reverseEdge(Edge e) {
alpar@1010
   362
      Node t=target(e);
alpar@1546
   363
      _changeTarget(e,source(e));
alpar@1546
   364
      _changeSource(e,t);
alpar@1010
   365
    }
alpar@1010
   366
alpar@1010
   367
    ///Using this it possible to avoid the superfluous memory allocation.
alpar@1010
   368
alpar@949
   369
    ///Using this it possible to avoid the superfluous memory allocation.
alpar@949
   370
    ///\todo more docs...
alpar@949
   371
    void reserveEdge(int n) { edges.reserve(n); };
alpar@1010
   372
alpar@1010
   373
    ///Contract two nodes.
alpar@1010
   374
alpar@1010
   375
    ///This function contracts two nodes.
alpar@1010
   376
    ///
alpar@1010
   377
    ///Node \p b will be removed but instead of deleting
alpar@1010
   378
    ///its neighboring edges, they will be joined to \p a.
alpar@1010
   379
    ///The last parameter \p r controls whether to remove loops. \c true
alpar@1010
   380
    ///means that loops will be removed.
alpar@1010
   381
    ///
alpar@1010
   382
    ///\note The <tt>Edge</tt>s
alpar@1281
   383
    ///referencing a moved edge remain
alpar@1010
   384
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1010
   385
    ///may be invalidated.
deba@1718
   386
    void contract(Node a, Node b, bool r = true) 
alpar@1010
   387
    {
alpar@1010
   388
      for(OutEdgeIt e(*this,b);e!=INVALID;) {
alpar@1010
   389
	OutEdgeIt f=e;
alpar@1010
   390
	++f;
alpar@1010
   391
	if(r && target(e)==a) erase(e);
alpar@1546
   392
	else changeSource(e,a);
alpar@1010
   393
	e=f;
alpar@1010
   394
      }
alpar@1010
   395
      for(InEdgeIt e(*this,b);e!=INVALID;) {
alpar@1010
   396
	InEdgeIt f=e;
alpar@1010
   397
	++f;
alpar@1010
   398
	if(r && source(e)==a) erase(e);
alpar@1546
   399
	else changeTarget(e,a);
alpar@1010
   400
	e=f;
alpar@1010
   401
      }
alpar@1010
   402
      erase(b);
alpar@1010
   403
    }
alpar@1011
   404
alpar@1281
   405
    ///Split a node.
alpar@1011
   406
alpar@1284
   407
    ///This function splits a node. First a new node is added to the graph,
alpar@1284
   408
    ///then the source of each outgoing edge of \c n is moved to this new node.
alpar@1281
   409
    ///If \c connect is \c true (this is the default value), then a new edge
alpar@1281
   410
    ///from \c n to the newly created node is also added.
alpar@1281
   411
    ///\return The newly created node.
alpar@1281
   412
    ///
alpar@1281
   413
    ///\note The <tt>Edge</tt>s
alpar@1281
   414
    ///referencing a moved edge remain
alpar@1281
   415
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1281
   416
    ///may be invalidated.
alpar@1770
   417
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1284
   418
    ///feature.
alpar@1281
   419
    ///\todo It could be implemented in a bit faster way.
alpar@1281
   420
    Node split(Node n, bool connect = true) 
alpar@1281
   421
    {
alpar@1281
   422
      Node b = addNode();
alpar@1281
   423
      for(OutEdgeIt e(*this,n);e!=INVALID;) {
alpar@1281
   424
 	OutEdgeIt f=e;
alpar@1281
   425
	++f;
alpar@1546
   426
	changeSource(e,b);
alpar@1281
   427
	e=f;
alpar@1281
   428
      }
alpar@1281
   429
      if(connect) addEdge(n,b);
alpar@1281
   430
      return b;
alpar@1281
   431
    }
alpar@1281
   432
      
alpar@1812
   433
    ///Split an edge.
alpar@1812
   434
alpar@1812
   435
    ///This function splits an edge. First a new node \c b is added to the graph,
alpar@1812
   436
    ///then the original edge is re-targetes to \c b. Finally an edge
alpar@1812
   437
    ///from \c b to the original target is added.
alpar@1812
   438
    ///\return The newly created node.
alpar@1812
   439
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1812
   440
    ///feature.
alpar@1812
   441
    Node split(Edge e) 
alpar@1812
   442
    {
alpar@1812
   443
      Node b = addNode();
alpar@1812
   444
      addEdge(b,target(e));
alpar@1812
   445
      changeTarget(e,b);
alpar@1812
   446
      return b;
alpar@1812
   447
    }
alpar@1812
   448
      
alpar@1011
   449
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   450
alpar@1011
   451
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   452
    ///
alpar@1011
   453
    ///The newly added nodes and edges can be removed using the
alpar@1011
   454
    ///restore() function.
alpar@1011
   455
    ///
alpar@1011
   456
    ///\warning Edge and node deletions cannot be restored.
alpar@1770
   457
    ///\warning Snapshots cannot be nested.
alpar@1770
   458
    class Snapshot : protected AlterationNotifier<Node>::ObserverBase,
deba@1039
   459
		     protected AlterationNotifier<Edge>::ObserverBase
alpar@1011
   460
    {
deba@1774
   461
    public:
deba@1774
   462
      
deba@1774
   463
      class UnsupportedOperation : public LogicError {
deba@1774
   464
      public:
deba@1774
   465
	virtual const char* exceptionName() const {
deba@1774
   466
	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
deba@1774
   467
	}
deba@1774
   468
      };
deba@1774
   469
            
deba@1774
   470
alpar@1011
   471
      protected:
alpar@1011
   472
      
alpar@1011
   473
      ListGraph *g;
alpar@1011
   474
      std::list<Node> added_nodes;
alpar@1011
   475
      std::list<Edge> added_edges;
alpar@1011
   476
      
alpar@1011
   477
      bool active;
alpar@1011
   478
      virtual void add(const Node& n) {
alpar@1011
   479
	added_nodes.push_back(n);
alpar@1011
   480
      };
alpar@1011
   481
      virtual void erase(const Node&) 
alpar@1011
   482
      {
deba@1774
   483
	throw UnsupportedOperation();
alpar@1011
   484
      }
alpar@1011
   485
      virtual void add(const Edge& n) {
alpar@1011
   486
	added_edges.push_back(n);
alpar@1011
   487
      };
alpar@1011
   488
      virtual void erase(const Edge&) 
alpar@1011
   489
      {
deba@1774
   490
	throw UnsupportedOperation();
alpar@1011
   491
      }
alpar@1011
   492
alpar@1457
   493
      ///\bug What is this used for?
alpar@1457
   494
      ///
alpar@1457
   495
      virtual void build() {}
alpar@1457
   496
      ///\bug What is this used for?
alpar@1457
   497
      ///
alpar@1457
   498
      virtual void clear() {}
alpar@1457
   499
alpar@1011
   500
      void regist(ListGraph &_g) {
alpar@1011
   501
	g=&_g;
deba@1039
   502
	AlterationNotifier<Node>::ObserverBase::
deba@1040
   503
	  attach(g->getNotifier(Node()));
deba@1039
   504
	AlterationNotifier<Edge>::ObserverBase::
deba@1040
   505
	  attach(g->getNotifier(Edge()));
alpar@1011
   506
      }
alpar@1011
   507
            
alpar@1011
   508
      void deregist() {
deba@1039
   509
	AlterationNotifier<Node>::ObserverBase::
alpar@1011
   510
	  detach();
deba@1039
   511
	AlterationNotifier<Edge>::ObserverBase::
alpar@1011
   512
	  detach();
alpar@1011
   513
	g=0;
alpar@1011
   514
      }
deba@1774
   515
alpar@1011
   516
    public:
alpar@1011
   517
      ///Default constructur.
alpar@1011
   518
      
alpar@1011
   519
      ///Default constructur.
alpar@1011
   520
      ///To actually make a snapshot you must call save().
alpar@1011
   521
      ///
alpar@1770
   522
      Snapshot() : g(0) {}
alpar@1011
   523
      ///Constructor that immediately makes a snapshot.
alpar@1011
   524
      
alpar@1011
   525
      ///This constructor immediately makes a snapshot of the graph.
alpar@1011
   526
      ///\param _g The graph we make a snapshot of.
alpar@1770
   527
      Snapshot(ListGraph &_g) {
alpar@1011
   528
	regist(_g);
alpar@1011
   529
      }
alpar@1011
   530
      ///\bug Is it necessary?
alpar@1011
   531
      ///
alpar@1770
   532
      ~Snapshot() 
alpar@1011
   533
      {
alpar@1011
   534
	if(g) deregist();
alpar@1011
   535
      }
alpar@1011
   536
      
alpar@1011
   537
      ///Make a snapshot.
alpar@1011
   538
alpar@1011
   539
      ///Make a snapshot of the graph.
alpar@1011
   540
      ///
alpar@1011
   541
      ///This function can be called more than once. In case of a repeated
alpar@1011
   542
      ///call, the previous snapshot gets lost.
alpar@1011
   543
      ///\param _g The graph we make the snapshot of.
alpar@1011
   544
      void save(ListGraph &_g) 
alpar@1011
   545
      {
alpar@1011
   546
	if(g!=&_g) {
alpar@1011
   547
	  if(g) deregist();
alpar@1011
   548
	  regist(_g);
alpar@1011
   549
	}
alpar@1011
   550
	added_nodes.clear();
alpar@1011
   551
	added_edges.clear();
alpar@1011
   552
      }
alpar@1011
   553
      
alpar@1011
   554
    ///Undo the changes until the last snapshot.
alpar@1011
   555
alpar@1011
   556
    ///Undo the changes until last snapshot created by save().
alpar@1011
   557
    ///
alpar@1011
   558
    ///\todo This function might be called undo().
alpar@1011
   559
      void restore() {
alpar@1457
   560
	ListGraph &old_g=*g;
alpar@1011
   561
	deregist();
alpar@1011
   562
	while(!added_edges.empty()) {
alpar@1457
   563
	  old_g.erase(added_edges.front());
alpar@1011
   564
	  added_edges.pop_front();
alpar@1011
   565
	}
alpar@1011
   566
 	while(!added_nodes.empty()) {
alpar@1457
   567
	  old_g.erase(added_nodes.front());
alpar@1011
   568
	  added_nodes.pop_front();
alpar@1011
   569
	}
alpar@1011
   570
      }
alpar@1011
   571
    };
alpar@1011
   572
    
alpar@949
   573
  };
klao@1034
   574
alpar@1555
   575
  ///@}
klao@1034
   576
klao@1034
   577
  /**************** Undirected List Graph ****************/
klao@1034
   578
klao@1034
   579
  typedef ErasableUndirGraphExtender<
klao@1034
   580
    ClearableUndirGraphExtender<
klao@1034
   581
    ExtendableUndirGraphExtender<
klao@1034
   582
    MappableUndirGraphExtender<
klao@1034
   583
    IterableUndirGraphExtender<
klao@1034
   584
    AlterableUndirGraphExtender<
deba@1669
   585
    UndirGraphExtender<ListGraphBase> > > > > > > ExtendedUndirListGraphBase;
klao@1034
   586
deba@1718
   587
  /// \addtogroup graphs
deba@1718
   588
  /// @{
alpar@1555
   589
alpar@1035
   590
  ///An undirected list graph class.
alpar@1035
   591
alpar@1035
   592
  ///This is a simple and fast erasable undirected graph implementation.
alpar@1035
   593
  ///
alpar@1035
   594
  ///It conforms to the
alpar@1035
   595
  ///\ref concept::UndirGraph "UndirGraph" concept.
alpar@1035
   596
  ///
alpar@1035
   597
  ///\sa concept::UndirGraph.
alpar@1035
   598
  ///
alpar@1770
   599
  ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
alpar@1161
   600
  ///haven't been implemented yet.
alpar@1035
   601
  ///
deba@1669
   602
  class UndirListGraph : public ExtendedUndirListGraphBase {
deba@1718
   603
  public:
deba@1718
   604
    typedef ExtendedUndirListGraphBase Parent;
deba@1718
   605
    /// \brief Changes the target of \c e to \c n
deba@1718
   606
    ///
deba@1718
   607
    /// Changes the target of \c e to \c n
deba@1718
   608
    ///
deba@1718
   609
    /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
deba@1718
   610
    /// referencing the changed edge remain
deba@1718
   611
    /// valid. However <tt>InEdge</tt>'s are invalidated.
deba@1718
   612
    void changeTarget(UndirEdge e, Node n) { 
deba@1718
   613
      _changeTarget(e,n); 
deba@1718
   614
    }
deba@1718
   615
    /// Changes the source of \c e to \c n
deba@1718
   616
    ///
deba@1718
   617
    /// Changes the source of \c e to \c n
deba@1718
   618
    ///
deba@1718
   619
    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
deba@1718
   620
    ///referencing the changed edge remain
deba@1718
   621
    ///valid. However <tt>OutEdge</tt>'s are invalidated.
deba@1718
   622
    void changeSource(UndirEdge e, Node n) { 
deba@1718
   623
      _changeSource(e,n); 
deba@1718
   624
    }
deba@1718
   625
    /// \brief Contract two nodes.
deba@1718
   626
    ///
deba@1718
   627
    /// This function contracts two nodes.
deba@1718
   628
    ///
deba@1718
   629
    /// Node \p b will be removed but instead of deleting
deba@1718
   630
    /// its neighboring edges, they will be joined to \p a.
deba@1718
   631
    /// The last parameter \p r controls whether to remove loops. \c true
deba@1718
   632
    /// means that loops will be removed.
deba@1718
   633
    ///
deba@1718
   634
    /// \note The <tt>Edge</tt>s
deba@1718
   635
    /// referencing a moved edge remain
deba@1718
   636
    /// valid.
deba@1718
   637
    void contract(Node a, Node b, bool r = true) {
deba@1718
   638
      for(IncEdgeIt e(*this, b); e!=INVALID;) {
deba@1718
   639
	IncEdgeIt f = e; ++f;
deba@1718
   640
	if (r && runningNode(e) == a) {
deba@1718
   641
	  erase(e);
deba@1718
   642
	} else if (source(e) == b) {
deba@1718
   643
	  changeSource(e, a);
deba@1718
   644
	} else {
deba@1718
   645
	  changeTarget(e, a);
deba@1718
   646
	}
deba@1718
   647
	e = f;
deba@1718
   648
      }
deba@1718
   649
      erase(b);
deba@1718
   650
    }
klao@1034
   651
  };
klao@1034
   652
alpar@949
   653
  
alpar@948
   654
  /// @}  
alpar@948
   655
} //namespace lemon
klao@946
   656
  
alpar@400
   657
klao@946
   658
#endif