lemon/unionfind.h
author ladanyi
Tue, 27 Nov 2007 16:26:58 +0000
changeset 2523 ceb7f3c704b7
parent 2505 1bb471764ab8
child 2542 faaa54ec4520
permissions -rw-r--r--
Fix warning when compiling with -Wall.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@2391
     5
 * Copyright (C) 2003-2007
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@906
    18
alpar@921
    19
#ifndef LEMON_UNION_FIND_H
alpar@921
    20
#define LEMON_UNION_FIND_H
beckerjc@483
    21
klao@491
    22
//!\ingroup auxdat
beckerjc@483
    23
//!\file
beckerjc@483
    24
//!\brief Union-Find data structures.
alpar@774
    25
//!
beckerjc@483
    26
beckerjc@483
    27
#include <vector>
beckerjc@483
    28
#include <list>
beckerjc@483
    29
#include <utility>
beckerjc@483
    30
#include <algorithm>
beckerjc@483
    31
deba@1993
    32
#include <lemon/bits/invalid.h>
beckerjc@483
    33
alpar@921
    34
namespace lemon {
beckerjc@483
    35
deba@2308
    36
  /// \ingroup auxdat
deba@2308
    37
  ///
deba@2205
    38
  /// \brief A \e Union-Find data structure implementation
deba@2205
    39
  ///
deba@2205
    40
  /// The class implements the \e Union-Find data structure. 
deba@2205
    41
  /// The union operation uses rank heuristic, while
deba@2205
    42
  /// the find operation uses path compression.
deba@2205
    43
  /// This is a very simple but efficient implementation, providing 
deba@2205
    44
  /// only four methods: join (union), find, insert and size.
deba@2205
    45
  /// For more features see the \ref UnionFindEnum class.
deba@2205
    46
  ///
deba@2205
    47
  /// It is primarily used in Kruskal algorithm for finding minimal
deba@2205
    48
  /// cost spanning tree in a graph.
deba@2205
    49
  /// \sa kruskal()
deba@2205
    50
  ///
deba@2205
    51
  /// \pre You need to add all the elements by the \ref insert()
deba@2205
    52
  /// method.  
deba@2308
    53
  template <typename _ItemIntMap>
beckerjc@483
    54
  class UnionFind {
beckerjc@483
    55
  public:
deba@2308
    56
deba@2308
    57
    typedef _ItemIntMap ItemIntMap;
deba@2308
    58
    typedef typename ItemIntMap::Key Item;
beckerjc@483
    59
beckerjc@483
    60
  private:
deba@2205
    61
    // If the items vector stores negative value for an item then
deba@2205
    62
    // that item is root item and it has -items[it] component size.
deba@2205
    63
    // Else the items[it] contains the index of the parent.
deba@2205
    64
    std::vector<int> items;
deba@2205
    65
    ItemIntMap& index;
deba@2205
    66
deba@2205
    67
    bool rep(int idx) const {
deba@2205
    68
      return items[idx] < 0;
deba@2205
    69
    }
deba@2205
    70
deba@2205
    71
    int repIndex(int idx) const {
deba@2205
    72
      int k = idx;
deba@2205
    73
      while (!rep(k)) {
deba@2205
    74
        k = items[k] ;
deba@2205
    75
      }
deba@2205
    76
      while (idx != k) {
deba@2205
    77
        int next = items[idx];
deba@2205
    78
        const_cast<int&>(items[idx]) = k;
deba@2205
    79
        idx = next;
deba@2205
    80
      }
deba@2205
    81
      return k;
deba@2205
    82
    }
beckerjc@483
    83
beckerjc@483
    84
  public:
beckerjc@483
    85
deba@2205
    86
    /// \brief Constructor
deba@2205
    87
    ///
deba@2205
    88
    /// Constructor of the UnionFind class. You should give an item to
deba@2205
    89
    /// integer map which will be used from the data structure. If you
deba@2205
    90
    /// modify directly this map that may cause segmentation fault,
deba@2205
    91
    /// invalid data structure, or infinite loop when you use again
deba@2205
    92
    /// the union-find.
deba@2205
    93
    UnionFind(ItemIntMap& m) : index(m) {}
beckerjc@483
    94
deba@2205
    95
    /// \brief Returns the index of the element's component.
deba@2205
    96
    ///
deba@2205
    97
    /// The method returns the index of the element's component.
deba@2205
    98
    /// This is an integer between zero and the number of inserted elements.
deba@2205
    99
    ///
deba@2205
   100
    int find(const Item& a) {
deba@2205
   101
      return repIndex(index[a]);
beckerjc@483
   102
    }
beckerjc@483
   103
deba@2427
   104
    /// \brief Clears the union-find data structure
deba@2427
   105
    ///
deba@2427
   106
    /// Erase each item from the data structure.
deba@2427
   107
    void clear() {
deba@2427
   108
      items.clear();
deba@2427
   109
    }
deba@2427
   110
deba@2205
   111
    /// \brief Inserts a new element into the structure.
deba@2205
   112
    ///
deba@2205
   113
    /// This method inserts a new element into the data structure. 
deba@2205
   114
    ///
deba@2205
   115
    /// The method returns the index of the new component.
deba@2205
   116
    int insert(const Item& a) {
deba@2205
   117
      int n = items.size();
deba@2205
   118
      items.push_back(-1);
deba@2205
   119
      index.set(a,n);
beckerjc@483
   120
      return n;
beckerjc@483
   121
    }
beckerjc@483
   122
deba@2205
   123
    /// \brief Joining the components of element \e a and element \e b.
deba@2205
   124
    ///
deba@2205
   125
    /// This is the \e union operation of the Union-Find structure. 
deba@2205
   126
    /// Joins the component of element \e a and component of
deba@2205
   127
    /// element \e b. If \e a and \e b are in the same component then
deba@2205
   128
    /// it returns false otherwise it returns true.
deba@2205
   129
    bool join(const Item& a, const Item& b) {
deba@2205
   130
      int ka = repIndex(index[a]);
deba@2205
   131
      int kb = repIndex(index[b]);
beckerjc@483
   132
deba@2205
   133
      if ( ka == kb ) 
beckerjc@483
   134
	return false;
beckerjc@483
   135
deba@2205
   136
      if (items[ka] < items[kb]) {
deba@2205
   137
	items[ka] += items[kb];
deba@2205
   138
	items[kb] = ka;
deba@2205
   139
      } else {
deba@2205
   140
	items[kb] += items[ka];
deba@2205
   141
	items[ka] = kb;
beckerjc@483
   142
      }
beckerjc@483
   143
      return true;
beckerjc@483
   144
    }
beckerjc@483
   145
deba@2205
   146
    /// \brief Returns the size of the component of element \e a.
deba@2205
   147
    ///
deba@2205
   148
    /// Returns the size of the component of element \e a.
deba@2205
   149
    int size(const Item& a) {
deba@2205
   150
      int k = repIndex(index[a]);
deba@2205
   151
      return - items[k];
beckerjc@483
   152
    }
beckerjc@483
   153
beckerjc@483
   154
  };
beckerjc@483
   155
deba@2308
   156
  /// \ingroup auxdat
deba@2308
   157
  ///
deba@2205
   158
  /// \brief A \e Union-Find data structure implementation which
deba@2205
   159
  /// is able to enumerate the components.
deba@2205
   160
  ///
deba@2205
   161
  /// The class implements a \e Union-Find data structure
deba@2205
   162
  /// which is able to enumerate the components and the items in
deba@2205
   163
  /// a component. If you don't need this feature then perhaps it's
deba@2205
   164
  /// better to use the \ref UnionFind class which is more efficient.
deba@2205
   165
  ///
deba@2205
   166
  /// The union operation uses rank heuristic, while
deba@2205
   167
  /// the find operation uses path compression.
deba@2205
   168
  ///
deba@2205
   169
  /// \pre You need to add all the elements by the \ref insert()
deba@2205
   170
  /// method.
deba@2205
   171
  ///
deba@2308
   172
  template <typename _ItemIntMap>
deba@2205
   173
  class UnionFindEnum {
deba@2205
   174
  public:
deba@2205
   175
    
deba@2205
   176
    typedef _ItemIntMap ItemIntMap;
deba@2308
   177
    typedef typename ItemIntMap::Key Item;
deba@2308
   178
deba@2205
   179
  private:
deba@2205
   180
    
deba@2505
   181
    ItemIntMap& index;
deba@2505
   182
deba@2205
   183
    // If the parent stores negative value for an item then that item
deba@2505
   184
    // is root item and it has ~(items[it].parent) component id.  Else
deba@2205
   185
    // the items[it].parent contains the index of the parent.
deba@2205
   186
    //
deba@2505
   187
    // The \c next and \c prev provides the double-linked
deba@2505
   188
    // cyclic list of one component's items.
deba@2205
   189
    struct ItemT {
deba@2205
   190
      int parent;
deba@2205
   191
      Item item;
beckerjc@483
   192
deba@2505
   193
      int next, prev;
deba@2205
   194
    };
beckerjc@483
   195
deba@2205
   196
    std::vector<ItemT> items;
deba@2505
   197
    int firstFreeItem;
beckerjc@483
   198
deba@2505
   199
    struct ClassT {
deba@2505
   200
      int size;
deba@2505
   201
      int firstItem;
deba@2505
   202
      int next, prev;
deba@2505
   203
    };
deba@2505
   204
    
deba@2505
   205
    std::vector<ClassT> classes;
deba@2505
   206
    int firstClass, firstFreeClass;
deba@2505
   207
deba@2505
   208
    int newClass() {
deba@2505
   209
      if (firstFreeClass == -1) {
deba@2505
   210
	int cdx = classes.size();
deba@2505
   211
	classes.push_back(ClassT());
deba@2505
   212
	return cdx;
deba@2505
   213
      } else {
deba@2505
   214
	int cdx = firstFreeClass;
deba@2505
   215
	firstFreeClass = classes[firstFreeClass].next;
deba@2505
   216
	return cdx;
deba@2505
   217
      }
deba@2505
   218
    }
deba@2505
   219
deba@2505
   220
    int newItem() {
deba@2505
   221
      if (firstFreeItem == -1) {
deba@2505
   222
	int idx = items.size();
deba@2505
   223
	items.push_back(ItemT());
deba@2505
   224
	return idx;
deba@2505
   225
      } else {
deba@2505
   226
	int idx = firstFreeItem;
deba@2505
   227
	firstFreeItem = items[firstFreeItem].next;
deba@2505
   228
	return idx;
deba@2505
   229
      }
deba@2505
   230
    }
beckerjc@483
   231
beckerjc@483
   232
deba@2205
   233
    bool rep(int idx) const {
deba@2205
   234
      return items[idx].parent < 0;
beckerjc@483
   235
    }
beckerjc@483
   236
deba@2205
   237
    int repIndex(int idx) const {
deba@2205
   238
      int k = idx;
deba@2205
   239
      while (!rep(k)) {
deba@2205
   240
        k = items[k].parent;
deba@2205
   241
      }
deba@2205
   242
      while (idx != k) {
deba@2205
   243
        int next = items[idx].parent;
deba@2205
   244
        const_cast<int&>(items[idx].parent) = k;
deba@2205
   245
        idx = next;
deba@2205
   246
      }
deba@2205
   247
      return k;
deba@2205
   248
    }
deba@2205
   249
deba@2505
   250
    int classIndex(int idx) const {
deba@2505
   251
      return ~(items[repIndex(idx)].parent);
deba@2505
   252
    }
deba@2505
   253
deba@2505
   254
    void singletonItem(int idx) {
deba@2505
   255
      items[idx].next = idx;
deba@2505
   256
      items[idx].prev = idx;
deba@2505
   257
    }
deba@2505
   258
deba@2505
   259
    void laceItem(int idx, int rdx) {
deba@2505
   260
      items[idx].prev = rdx;
deba@2505
   261
      items[idx].next = items[rdx].next;
deba@2505
   262
      items[items[rdx].next].prev = idx;
deba@2505
   263
      items[rdx].next = idx;
deba@2505
   264
    }
deba@2505
   265
deba@2505
   266
    void unlaceItem(int idx) {
deba@2505
   267
      items[items[idx].prev].next = items[idx].next;
deba@2505
   268
      items[items[idx].next].prev = items[idx].prev;
deba@2505
   269
      
deba@2505
   270
      items[idx].next = firstFreeItem;
deba@2505
   271
      firstFreeItem = idx;
deba@2505
   272
    }
deba@2505
   273
deba@2505
   274
    void spliceItems(int ak, int bk) {
deba@2505
   275
      items[items[ak].prev].next = bk;
deba@2505
   276
      items[items[bk].prev].next = ak;
deba@2505
   277
      int tmp = items[ak].prev;
deba@2505
   278
      items[ak].prev = items[bk].prev;
deba@2505
   279
      items[bk].prev = tmp;
deba@2505
   280
        
deba@2505
   281
    }
deba@2505
   282
deba@2505
   283
    void laceClass(int cls) {
deba@2505
   284
      if (firstClass != -1) {
deba@2505
   285
        classes[firstClass].prev = cls;
deba@2205
   286
      }
deba@2505
   287
      classes[cls].next = firstClass;
deba@2505
   288
      classes[cls].prev = -1;
deba@2505
   289
      firstClass = cls;
deba@2205
   290
    } 
deba@2205
   291
deba@2505
   292
    void unlaceClass(int cls) {
deba@2505
   293
      if (classes[cls].prev != -1) {
deba@2505
   294
        classes[classes[cls].prev].next = classes[cls].next;
deba@2505
   295
      } else {
deba@2505
   296
        firstClass = classes[cls].next;
deba@2505
   297
      }
deba@2505
   298
      if (classes[cls].next != -1) {
deba@2505
   299
        classes[classes[cls].next].prev = classes[cls].prev;
deba@2505
   300
      }
deba@2505
   301
      
deba@2505
   302
      classes[cls].next = firstFreeClass;
deba@2505
   303
      firstFreeClass = cls;
deba@2505
   304
    } 
klao@2003
   305
beckerjc@483
   306
  public:
beckerjc@483
   307
deba@2205
   308
    UnionFindEnum(ItemIntMap& _index) 
deba@2505
   309
      : index(_index), items(), firstFreeItem(-1), 
deba@2505
   310
	firstClass(-1), firstFreeClass(-1) {}
deba@2205
   311
    
deba@2205
   312
    /// \brief Inserts the given element into a new component.
deba@2205
   313
    ///
deba@2205
   314
    /// This method creates a new component consisting only of the
deba@2205
   315
    /// given element.
deba@2205
   316
    ///
deba@2505
   317
    int insert(const Item& item) {
deba@2505
   318
      int idx = newItem();
beckerjc@483
   319
deba@2205
   320
      index.set(item, idx);
beckerjc@483
   321
deba@2505
   322
      singletonItem(idx);
deba@2505
   323
      items[idx].item = item;
deba@2505
   324
deba@2505
   325
      int cdx = newClass();
deba@2505
   326
deba@2505
   327
      items[idx].parent = ~cdx;
deba@2505
   328
deba@2505
   329
      laceClass(cdx);
deba@2505
   330
      classes[cdx].size = 1;
deba@2505
   331
      classes[cdx].firstItem = idx;
deba@2505
   332
deba@2505
   333
      firstClass = cdx;
deba@2205
   334
      
deba@2505
   335
      return cdx;
beckerjc@483
   336
    }
beckerjc@483
   337
deba@2205
   338
    /// \brief Inserts the given element into the component of the others.
deba@2205
   339
    ///
deba@2205
   340
    /// This methods inserts the element \e a into the component of the
deba@2205
   341
    /// element \e comp. 
deba@2505
   342
    void insert(const Item& item, int cls) {
deba@2505
   343
      int rdx = classes[cls].firstItem;
deba@2505
   344
      int idx = newItem();
beckerjc@483
   345
deba@2205
   346
      index.set(item, idx);
deba@2205
   347
deba@2505
   348
      laceItem(idx, rdx);
deba@2205
   349
deba@2505
   350
      items[idx].item = item;
deba@2505
   351
      items[idx].parent = rdx;
deba@2205
   352
deba@2505
   353
      ++classes[~(items[rdx].parent)].size;
beckerjc@483
   354
    }
beckerjc@483
   355
deba@2427
   356
    /// \brief Clears the union-find data structure
deba@2427
   357
    ///
deba@2427
   358
    /// Erase each item from the data structure.
deba@2427
   359
    void clear() {
deba@2427
   360
      items.clear();
deba@2427
   361
      firstClass = -1;
deba@2505
   362
      firstFreeItem = -1;
deba@2427
   363
    }
deba@2427
   364
deba@2505
   365
    /// \brief Finds the component of the given element.
deba@2205
   366
    ///
deba@2505
   367
    /// The method returns the component id of the given element.
deba@2505
   368
    int find(const Item &item) const {
deba@2505
   369
      return ~(items[repIndex(index[item])].parent);
beckerjc@483
   370
    }
beckerjc@483
   371
deba@2205
   372
    /// \brief Joining the component of element \e a and element \e b.
deba@2205
   373
    ///
deba@2205
   374
    /// This is the \e union operation of the Union-Find structure. 
deba@2205
   375
    /// Joins the component of element \e a and component of
deba@2205
   376
    /// element \e b. If \e a and \e b are in the same component then
deba@2505
   377
    /// returns -1 else returns the remaining class.
deba@2505
   378
    int join(const Item& a, const Item& b) {
beckerjc@483
   379
deba@2205
   380
      int ak = repIndex(index[a]);
deba@2205
   381
      int bk = repIndex(index[b]);
beckerjc@483
   382
deba@2205
   383
      if (ak == bk) {
deba@2505
   384
	return -1;
beckerjc@483
   385
      }
beckerjc@483
   386
deba@2505
   387
      int acx = ~(items[ak].parent);
deba@2505
   388
      int bcx = ~(items[bk].parent);
deba@2505
   389
deba@2505
   390
      int rcx;
deba@2505
   391
deba@2505
   392
      if (classes[acx].size > classes[bcx].size) {
deba@2505
   393
	classes[acx].size += classes[bcx].size;
deba@2205
   394
	items[bk].parent = ak;
deba@2505
   395
        unlaceClass(bcx);
deba@2505
   396
	rcx = acx;
deba@2205
   397
      } else {
deba@2505
   398
	classes[bcx].size += classes[acx].size;
deba@2205
   399
	items[ak].parent = bk;
deba@2505
   400
        unlaceClass(acx);
deba@2505
   401
	rcx = bcx;
beckerjc@483
   402
      }
deba@2205
   403
      spliceItems(ak, bk);
beckerjc@483
   404
deba@2505
   405
      return rcx;
beckerjc@483
   406
    }
beckerjc@483
   407
deba@2505
   408
    /// \brief Returns the size of the class.
deba@2205
   409
    ///
deba@2505
   410
    /// Returns the size of the class.
deba@2505
   411
    int size(int cls) const {
deba@2505
   412
      return classes[cls].size;
beckerjc@483
   413
    }
beckerjc@483
   414
deba@2505
   415
    /// \brief Splits up the component. 
deba@2205
   416
    ///
deba@2505
   417
    /// Splitting the component into singleton components (component
deba@2505
   418
    /// of size one).
deba@2505
   419
    void split(int cls) {
deba@2505
   420
      int fdx = classes[cls].firstItem;
deba@2505
   421
      int idx = items[fdx].next;
deba@2505
   422
      while (idx != fdx) {
deba@2505
   423
        int next = items[idx].next;
deba@2505
   424
deba@2505
   425
	singletonItem(idx);
deba@2505
   426
deba@2505
   427
	int cdx = newClass();        
deba@2505
   428
        items[idx].parent = ~cdx;
deba@2505
   429
deba@2505
   430
	laceClass(cdx);
deba@2505
   431
	classes[cdx].size = 1;
deba@2505
   432
	classes[cdx].firstItem = idx;
deba@2205
   433
        
deba@2205
   434
        idx = next;
beckerjc@483
   435
      }
beckerjc@483
   436
deba@2505
   437
      items[idx].prev = idx;
deba@2505
   438
      items[idx].next = idx;
deba@2505
   439
deba@2505
   440
      classes[~(items[idx].parent)].size = 1;
deba@2205
   441
      
beckerjc@483
   442
    }
beckerjc@483
   443
deba@2205
   444
    /// \brief Removes the given element from the structure.
deba@2205
   445
    ///
deba@2205
   446
    /// Removes the element from its component and if the component becomes
deba@2205
   447
    /// empty then removes that component from the component list.
deba@2205
   448
    ///
deba@2205
   449
    /// \warning It is an error to remove an element which is not in
deba@2205
   450
    /// the structure.
deba@2505
   451
    /// \warning This running time of this operation is proportional to the
deba@2505
   452
    /// number of the items in this class.
deba@2505
   453
    void erase(const Item& item) {
deba@2205
   454
      int idx = index[item];
deba@2505
   455
      int fdx = items[idx].next;
deba@2505
   456
deba@2505
   457
      int cdx = classIndex(idx);
deba@2505
   458
      if (idx == fdx) {
deba@2505
   459
	unlaceClass(cdx);
deba@2505
   460
	items[idx].next = firstFreeItem;
deba@2505
   461
	firstFreeItem = idx;
deba@2505
   462
	return;
deba@2505
   463
      } else {
deba@2505
   464
	classes[cdx].firstItem = fdx;
deba@2505
   465
	--classes[cdx].size;
deba@2505
   466
	items[fdx].parent = ~cdx;
deba@2505
   467
deba@2505
   468
	unlaceItem(idx);
deba@2505
   469
	idx = items[fdx].next;
deba@2505
   470
	while (idx != fdx) {
deba@2505
   471
	  items[idx].parent = fdx;
deba@2505
   472
	  idx = items[idx].next;
deba@2505
   473
	}
deba@2205
   474
          
beckerjc@483
   475
      }
beckerjc@483
   476
deba@2506
   477
    }
deba@2506
   478
deba@2506
   479
    /// \brief Gives back a representant item of the component.
deba@2506
   480
    ///
deba@2506
   481
    /// Gives back a representant item of the component.
deba@2506
   482
    Item item(int cls) const {
deba@2506
   483
      return items[classes[cls].firstItem].item;
deba@2506
   484
    }
beckerjc@483
   485
deba@2205
   486
    /// \brief Removes the component of the given element from the structure.
deba@2205
   487
    ///
deba@2205
   488
    /// Removes the component of the given element from the structure.
deba@2205
   489
    ///
deba@2205
   490
    /// \warning It is an error to give an element which is not in the
deba@2205
   491
    /// structure.
deba@2505
   492
    void eraseClass(int cls) {
deba@2505
   493
      int fdx = classes[cls].firstItem;
deba@2505
   494
      unlaceClass(cls);
deba@2505
   495
      items[items[fdx].prev].next = firstFreeItem;
deba@2505
   496
      firstFreeItem = fdx;
deba@2205
   497
    }
beckerjc@483
   498
deba@2205
   499
    /// \brief Lemon style iterator for the representant items.
deba@2205
   500
    ///
deba@2205
   501
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2505
   502
    /// on the ids of the classes.
deba@2205
   503
    class ClassIt {
deba@2205
   504
    public:
deba@2205
   505
      /// \brief Constructor of the iterator
deba@2205
   506
      ///
deba@2205
   507
      /// Constructor of the iterator
deba@2205
   508
      ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
deba@2505
   509
        cdx = unionFind->firstClass;
beckerjc@483
   510
      }
beckerjc@483
   511
deba@2205
   512
      /// \brief Constructor to get invalid iterator
deba@2205
   513
      ///
deba@2205
   514
      /// Constructor to get invalid iterator
deba@2505
   515
      ClassIt(Invalid) : unionFind(0), cdx(-1) {}
deba@2205
   516
      
deba@2205
   517
      /// \brief Increment operator
deba@2205
   518
      ///
deba@2205
   519
      /// It steps to the next representant item.
deba@2205
   520
      ClassIt& operator++() {
deba@2505
   521
        cdx = unionFind->classes[cdx].next;
deba@2205
   522
        return *this;
deba@2205
   523
      }
deba@2205
   524
      
deba@2205
   525
      /// \brief Conversion operator
deba@2205
   526
      ///
deba@2205
   527
      /// It converts the iterator to the current representant item.
deba@2505
   528
      operator int() const {
deba@2505
   529
        return cdx;
beckerjc@483
   530
      }
beckerjc@483
   531
deba@2205
   532
      /// \brief Equality operator
deba@2205
   533
      ///
deba@2205
   534
      /// Equality operator
deba@2205
   535
      bool operator==(const ClassIt& i) { 
deba@2505
   536
        return i.cdx == cdx;
deba@2205
   537
      }
beckerjc@483
   538
deba@2205
   539
      /// \brief Inequality operator
deba@2205
   540
      ///
deba@2205
   541
      /// Inequality operator
deba@2205
   542
      bool operator!=(const ClassIt& i) { 
deba@2505
   543
        return i.cdx != cdx;
klao@2003
   544
      }
beckerjc@483
   545
      
deba@2205
   546
    private:
deba@2205
   547
      const UnionFindEnum* unionFind;
deba@2505
   548
      int cdx;
deba@2205
   549
    };
deba@2205
   550
deba@2205
   551
    /// \brief Lemon style iterator for the items of a component.
deba@2205
   552
    ///
deba@2205
   553
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2205
   554
    /// on the items of a class. By example if you want to iterate on
deba@2205
   555
    /// each items of each classes then you may write the next code.
deba@2205
   556
    ///\code
deba@2205
   557
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
deba@2205
   558
    ///   std::cout << "Class: ";
deba@2205
   559
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
deba@2205
   560
    ///     std::cout << toString(iit) << ' ' << std::endl;
deba@2205
   561
    ///   }
deba@2205
   562
    ///   std::cout << std::endl;
deba@2205
   563
    /// }
deba@2205
   564
    ///\endcode
deba@2205
   565
    class ItemIt {
deba@2205
   566
    public:
deba@2205
   567
      /// \brief Constructor of the iterator
deba@2205
   568
      ///
deba@2205
   569
      /// Constructor of the iterator. The iterator iterates
deba@2205
   570
      /// on the class of the \c item.
deba@2505
   571
      ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
deba@2505
   572
        fdx = idx = unionFind->classes[cls].firstItem;
beckerjc@483
   573
      }
beckerjc@483
   574
deba@2205
   575
      /// \brief Constructor to get invalid iterator
deba@2205
   576
      ///
deba@2205
   577
      /// Constructor to get invalid iterator
deba@2205
   578
      ItemIt(Invalid) : unionFind(0), idx(-1) {}
deba@2205
   579
      
deba@2205
   580
      /// \brief Increment operator
deba@2205
   581
      ///
deba@2205
   582
      /// It steps to the next item in the class.
deba@2205
   583
      ItemIt& operator++() {
deba@2505
   584
        idx = unionFind->items[idx].next;
deba@2505
   585
        if (idx == fdx) idx = -1;
deba@2205
   586
        return *this;
klao@2003
   587
      }
deba@2205
   588
      
deba@2205
   589
      /// \brief Conversion operator
deba@2205
   590
      ///
deba@2205
   591
      /// It converts the iterator to the current item.
deba@2205
   592
      operator const Item&() const {
deba@2205
   593
        return unionFind->items[idx].item;
klao@2003
   594
      }
klao@2003
   595
deba@2205
   596
      /// \brief Equality operator
deba@2205
   597
      ///
deba@2205
   598
      /// Equality operator
deba@2205
   599
      bool operator==(const ItemIt& i) { 
deba@2205
   600
        return i.idx == idx;
klao@2003
   601
      }
klao@2003
   602
deba@2205
   603
      /// \brief Inequality operator
deba@2205
   604
      ///
deba@2205
   605
      /// Inequality operator
deba@2205
   606
      bool operator!=(const ItemIt& i) { 
deba@2205
   607
        return i.idx != idx;
deba@2205
   608
      }
deba@2205
   609
      
deba@2205
   610
    private:
deba@2205
   611
      const UnionFindEnum* unionFind;
deba@2505
   612
      int idx, fdx;
beckerjc@483
   613
    };
beckerjc@483
   614
beckerjc@483
   615
  };
beckerjc@483
   616
deba@2505
   617
  /// \ingroup auxdat
deba@2505
   618
  ///
deba@2505
   619
  /// \brief A \e Extend-Find data structure implementation which
deba@2505
   620
  /// is able to enumerate the components.
deba@2505
   621
  ///
deba@2505
   622
  /// The class implements an \e Extend-Find data structure which is
deba@2505
   623
  /// able to enumerate the components and the items in a
deba@2505
   624
  /// component. The data structure is a simplification of the
deba@2505
   625
  /// Union-Find structure, and it does not allow to merge two components.
deba@2505
   626
  ///
deba@2505
   627
  /// \pre You need to add all the elements by the \ref insert()
deba@2505
   628
  /// method.
deba@2505
   629
  template <typename _ItemIntMap>
deba@2505
   630
  class ExtendFindEnum {
deba@2505
   631
  public:
deba@2505
   632
    
deba@2505
   633
    typedef _ItemIntMap ItemIntMap;
deba@2505
   634
    typedef typename ItemIntMap::Key Item;
deba@2505
   635
deba@2505
   636
  private:
deba@2505
   637
    
deba@2505
   638
    ItemIntMap& index;
deba@2505
   639
deba@2505
   640
    struct ItemT {
deba@2505
   641
      int cls;
deba@2505
   642
      Item item;
deba@2505
   643
      int next, prev;
deba@2505
   644
    };
deba@2505
   645
deba@2505
   646
    std::vector<ItemT> items;
deba@2505
   647
    int firstFreeItem;
deba@2505
   648
deba@2505
   649
    struct ClassT {
deba@2505
   650
      int firstItem;
deba@2505
   651
      int next, prev;
deba@2505
   652
    };
deba@2505
   653
deba@2505
   654
    std::vector<ClassT> classes;
deba@2505
   655
deba@2505
   656
    int firstClass, firstFreeClass;
deba@2505
   657
deba@2505
   658
    int newClass() {
deba@2505
   659
      if (firstFreeClass != -1) {
deba@2505
   660
	int cdx = firstFreeClass;
deba@2505
   661
	firstFreeClass = classes[cdx].next;
deba@2505
   662
	return cdx;
deba@2505
   663
      } else {
deba@2505
   664
	classes.push_back(ClassT());
deba@2505
   665
	return classes.size() - 1;
deba@2505
   666
      }
deba@2505
   667
    }
deba@2505
   668
deba@2505
   669
    int newItem() {
deba@2505
   670
      if (firstFreeItem != -1) {
deba@2505
   671
	int idx = firstFreeItem;
deba@2505
   672
	firstFreeItem = items[idx].next;
deba@2505
   673
	return idx;
deba@2505
   674
      } else {
deba@2505
   675
	items.push_back(ItemT());
deba@2505
   676
	return items.size() - 1;
deba@2505
   677
      }
deba@2505
   678
    }
deba@2505
   679
deba@2505
   680
  public:
deba@2505
   681
deba@2505
   682
    /// \brief Constructor
deba@2505
   683
    ExtendFindEnum(ItemIntMap& _index) 
deba@2505
   684
      : index(_index), items(), firstFreeItem(-1), 
deba@2505
   685
	classes(), firstClass(-1), firstFreeClass(-1) {}
deba@2505
   686
    
deba@2505
   687
    /// \brief Inserts the given element into a new component.
deba@2505
   688
    ///
deba@2505
   689
    /// This method creates a new component consisting only of the
deba@2505
   690
    /// given element.
deba@2505
   691
    int insert(const Item& item) {
deba@2505
   692
      int cdx = newClass();
deba@2505
   693
      classes[cdx].prev = -1;
deba@2505
   694
      classes[cdx].next = firstClass;
deba@2505
   695
      firstClass = cdx;
deba@2505
   696
      
deba@2505
   697
      int idx = newItem();
deba@2505
   698
      items[idx].item = item;
deba@2505
   699
      items[idx].cls = cdx;
deba@2505
   700
      items[idx].prev = idx;
deba@2505
   701
      items[idx].next = idx;
deba@2505
   702
deba@2505
   703
      classes[cdx].firstItem = idx;
deba@2505
   704
deba@2505
   705
      index.set(item, idx);
deba@2505
   706
      
deba@2505
   707
      return cdx;
deba@2505
   708
    }
deba@2505
   709
deba@2505
   710
    /// \brief Inserts the given element into the given component.
deba@2505
   711
    ///
deba@2505
   712
    /// This methods inserts the element \e item a into the \e cls class.
deba@2505
   713
    void insert(const Item& item, int cls) {
deba@2505
   714
      int idx = newItem();
deba@2505
   715
      int rdx = classes[cls].firstItem;
deba@2505
   716
      items[idx].item = item;
deba@2505
   717
      items[idx].cls = cls;
deba@2505
   718
deba@2505
   719
      items[idx].prev = rdx;
deba@2505
   720
      items[idx].next = items[rdx].next;
deba@2505
   721
      items[items[rdx].next].prev = idx;
deba@2505
   722
      items[rdx].next = idx;
deba@2505
   723
deba@2505
   724
      index.set(item, idx);
deba@2505
   725
    }
deba@2505
   726
deba@2505
   727
    /// \brief Clears the union-find data structure
deba@2505
   728
    ///
deba@2505
   729
    /// Erase each item from the data structure.
deba@2505
   730
    void clear() {
deba@2505
   731
      items.clear();
deba@2505
   732
      classes.clear;
deba@2505
   733
      firstClass = firstFreeClass = firstFreeItem = -1;
deba@2505
   734
    }
deba@2505
   735
deba@2505
   736
    /// \brief Gives back the class of the \e item.
deba@2505
   737
    ///
deba@2505
   738
    /// Gives back the class of the \e item.
deba@2505
   739
    int find(const Item &item) const {
deba@2505
   740
      return items[index[item]].cls;
deba@2505
   741
    }
deba@2506
   742
deba@2506
   743
    /// \brief Gives back a representant item of the component.
deba@2506
   744
    ///
deba@2506
   745
    /// Gives back a representant item of the component.
deba@2506
   746
    Item item(int cls) const {
deba@2506
   747
      return items[classes[cls].firstItem].item;
deba@2506
   748
    }
deba@2505
   749
    
deba@2505
   750
    /// \brief Removes the given element from the structure.
deba@2505
   751
    ///
deba@2505
   752
    /// Removes the element from its component and if the component becomes
deba@2505
   753
    /// empty then removes that component from the component list.
deba@2505
   754
    ///
deba@2505
   755
    /// \warning It is an error to remove an element which is not in
deba@2505
   756
    /// the structure.
deba@2505
   757
    void erase(const Item &item) {
deba@2505
   758
      int idx = index[item];
deba@2505
   759
      int cdx = items[idx].cls;
deba@2505
   760
      
deba@2505
   761
      if (idx == items[idx].next) {
deba@2505
   762
	if (classes[cdx].prev != -1) {
deba@2505
   763
	  classes[classes[cdx].prev].next = classes[cdx].next; 
deba@2505
   764
	} else {
deba@2505
   765
	  firstClass = classes[cdx].next;
deba@2505
   766
	}
deba@2505
   767
	if (classes[cdx].next != -1) {
deba@2505
   768
	  classes[classes[cdx].next].prev = classes[cdx].prev; 
deba@2505
   769
	}
deba@2505
   770
	classes[cdx].next = firstFreeClass;
deba@2505
   771
	firstFreeClass = cdx;
deba@2505
   772
      } else {
deba@2505
   773
	classes[cdx].firstItem = items[idx].next;
deba@2505
   774
	items[items[idx].next].prev = items[idx].prev;
deba@2505
   775
	items[items[idx].prev].next = items[idx].next;
deba@2505
   776
      }
deba@2505
   777
      items[idx].next = firstFreeItem;
deba@2505
   778
      firstFreeItem = idx;
deba@2505
   779
	
deba@2505
   780
    }    
deba@2505
   781
deba@2505
   782
    
deba@2505
   783
    /// \brief Removes the component of the given element from the structure.
deba@2505
   784
    ///
deba@2505
   785
    /// Removes the component of the given element from the structure.
deba@2505
   786
    ///
deba@2505
   787
    /// \warning It is an error to give an element which is not in the
deba@2505
   788
    /// structure.
deba@2505
   789
    void eraseClass(int cdx) {
deba@2505
   790
      int idx = classes[cdx].firstItem;
deba@2505
   791
      items[items[idx].prev].next = firstFreeItem;
deba@2505
   792
      firstFreeItem = idx;
deba@2505
   793
deba@2505
   794
      if (classes[cdx].prev != -1) {
deba@2505
   795
	classes[classes[cdx].prev].next = classes[cdx].next; 
deba@2505
   796
      } else {
deba@2505
   797
	firstClass = classes[cdx].next;
deba@2505
   798
      }
deba@2505
   799
      if (classes[cdx].next != -1) {
deba@2505
   800
	classes[classes[cdx].next].prev = classes[cdx].prev; 
deba@2505
   801
      }
deba@2505
   802
      classes[cdx].next = firstFreeClass;
deba@2505
   803
      firstFreeClass = cdx;
deba@2505
   804
    }
deba@2505
   805
deba@2505
   806
    /// \brief Lemon style iterator for the classes.
deba@2505
   807
    ///
deba@2505
   808
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2505
   809
    /// on the ids of classes.
deba@2505
   810
    class ClassIt {
deba@2505
   811
    public:
deba@2505
   812
      /// \brief Constructor of the iterator
deba@2505
   813
      ///
deba@2505
   814
      /// Constructor of the iterator
deba@2505
   815
      ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
deba@2505
   816
        cdx = extendFind->firstClass;
deba@2505
   817
      }
deba@2505
   818
deba@2505
   819
      /// \brief Constructor to get invalid iterator
deba@2505
   820
      ///
deba@2505
   821
      /// Constructor to get invalid iterator
deba@2505
   822
      ClassIt(Invalid) : extendFind(0), cdx(-1) {}
deba@2505
   823
      
deba@2505
   824
      /// \brief Increment operator
deba@2505
   825
      ///
deba@2505
   826
      /// It steps to the next representant item.
deba@2505
   827
      ClassIt& operator++() {
deba@2505
   828
        cdx = extendFind->classes[cdx].next;
deba@2505
   829
        return *this;
deba@2505
   830
      }
deba@2505
   831
      
deba@2505
   832
      /// \brief Conversion operator
deba@2505
   833
      ///
deba@2505
   834
      /// It converts the iterator to the current class id.
deba@2505
   835
      operator int() const {
deba@2505
   836
        return cdx;
deba@2505
   837
      }
deba@2505
   838
deba@2505
   839
      /// \brief Equality operator
deba@2505
   840
      ///
deba@2505
   841
      /// Equality operator
deba@2505
   842
      bool operator==(const ClassIt& i) { 
deba@2505
   843
        return i.cdx == cdx;
deba@2505
   844
      }
deba@2505
   845
deba@2505
   846
      /// \brief Inequality operator
deba@2505
   847
      ///
deba@2505
   848
      /// Inequality operator
deba@2505
   849
      bool operator!=(const ClassIt& i) { 
deba@2505
   850
        return i.cdx != cdx;
deba@2505
   851
      }
deba@2505
   852
      
deba@2505
   853
    private:
deba@2505
   854
      const ExtendFindEnum* extendFind;
deba@2505
   855
      int cdx;
deba@2505
   856
    };
deba@2505
   857
deba@2505
   858
    /// \brief Lemon style iterator for the items of a component.
deba@2505
   859
    ///
deba@2505
   860
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2505
   861
    /// on the items of a class. By example if you want to iterate on
deba@2505
   862
    /// each items of each classes then you may write the next code.
deba@2505
   863
    ///\code
deba@2505
   864
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
deba@2505
   865
    ///   std::cout << "Class: ";
deba@2505
   866
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
deba@2505
   867
    ///     std::cout << toString(iit) << ' ' << std::endl;
deba@2505
   868
    ///   }
deba@2505
   869
    ///   std::cout << std::endl;
deba@2505
   870
    /// }
deba@2505
   871
    ///\endcode
deba@2505
   872
    class ItemIt {
deba@2505
   873
    public:
deba@2505
   874
      /// \brief Constructor of the iterator
deba@2505
   875
      ///
deba@2505
   876
      /// Constructor of the iterator. The iterator iterates
deba@2505
   877
      /// on the class of the \c item.
deba@2505
   878
      ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
deba@2505
   879
        fdx = idx = extendFind->classes[cls].firstItem;
deba@2505
   880
      }
deba@2505
   881
deba@2505
   882
      /// \brief Constructor to get invalid iterator
deba@2505
   883
      ///
deba@2505
   884
      /// Constructor to get invalid iterator
deba@2505
   885
      ItemIt(Invalid) : extendFind(0), idx(-1) {}
deba@2505
   886
      
deba@2505
   887
      /// \brief Increment operator
deba@2505
   888
      ///
deba@2505
   889
      /// It steps to the next item in the class.
deba@2505
   890
      ItemIt& operator++() {
deba@2505
   891
        idx = extendFind->items[idx].next;
deba@2505
   892
	if (fdx == idx) idx = -1;
deba@2505
   893
        return *this;
deba@2505
   894
      }
deba@2505
   895
      
deba@2505
   896
      /// \brief Conversion operator
deba@2505
   897
      ///
deba@2505
   898
      /// It converts the iterator to the current item.
deba@2505
   899
      operator const Item&() const {
deba@2505
   900
        return extendFind->items[idx].item;
deba@2505
   901
      }
deba@2505
   902
deba@2505
   903
      /// \brief Equality operator
deba@2505
   904
      ///
deba@2505
   905
      /// Equality operator
deba@2505
   906
      bool operator==(const ItemIt& i) { 
deba@2505
   907
        return i.idx == idx;
deba@2505
   908
      }
deba@2505
   909
deba@2505
   910
      /// \brief Inequality operator
deba@2505
   911
      ///
deba@2505
   912
      /// Inequality operator
deba@2505
   913
      bool operator!=(const ItemIt& i) { 
deba@2505
   914
        return i.idx != idx;
deba@2505
   915
      }
deba@2505
   916
      
deba@2505
   917
    private:
deba@2505
   918
      const ExtendFindEnum* extendFind;
deba@2505
   919
      int idx, fdx;
deba@2505
   920
    };
deba@2505
   921
deba@2505
   922
  };
beckerjc@483
   923
beckerjc@483
   924
  //! @}
beckerjc@483
   925
alpar@921
   926
} //namespace lemon
beckerjc@483
   927
alpar@921
   928
#endif //LEMON_UNION_FIND_H