lemon/unionfind.h
author convert-repo
Thu, 04 Mar 2010 19:34:55 +0000
changeset 2659 611ced85018b
parent 2631 212ea31bf6b9
permissions -rw-r--r--
update tags
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@2553
     5
 * Copyright (C) 2003-2008
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>
ladanyi@2551
    31
#include <functional>
beckerjc@483
    32
deba@1993
    33
#include <lemon/bits/invalid.h>
beckerjc@483
    34
alpar@921
    35
namespace lemon {
beckerjc@483
    36
deba@2308
    37
  /// \ingroup auxdat
deba@2308
    38
  ///
deba@2205
    39
  /// \brief A \e Union-Find data structure implementation
deba@2205
    40
  ///
deba@2205
    41
  /// The class implements the \e Union-Find data structure. 
deba@2205
    42
  /// The union operation uses rank heuristic, while
deba@2205
    43
  /// the find operation uses path compression.
deba@2205
    44
  /// This is a very simple but efficient implementation, providing 
deba@2205
    45
  /// only four methods: join (union), find, insert and size.
deba@2205
    46
  /// For more features see the \ref UnionFindEnum class.
deba@2205
    47
  ///
deba@2205
    48
  /// It is primarily used in Kruskal algorithm for finding minimal
deba@2205
    49
  /// cost spanning tree in a graph.
deba@2205
    50
  /// \sa kruskal()
deba@2205
    51
  ///
deba@2205
    52
  /// \pre You need to add all the elements by the \ref insert()
deba@2205
    53
  /// method.  
deba@2308
    54
  template <typename _ItemIntMap>
beckerjc@483
    55
  class UnionFind {
beckerjc@483
    56
  public:
deba@2308
    57
deba@2308
    58
    typedef _ItemIntMap ItemIntMap;
deba@2308
    59
    typedef typename ItemIntMap::Key Item;
beckerjc@483
    60
beckerjc@483
    61
  private:
deba@2205
    62
    // If the items vector stores negative value for an item then
deba@2205
    63
    // that item is root item and it has -items[it] component size.
deba@2205
    64
    // Else the items[it] contains the index of the parent.
deba@2205
    65
    std::vector<int> items;
deba@2205
    66
    ItemIntMap& index;
deba@2205
    67
deba@2205
    68
    bool rep(int idx) const {
deba@2205
    69
      return items[idx] < 0;
deba@2205
    70
    }
deba@2205
    71
deba@2205
    72
    int repIndex(int idx) const {
deba@2205
    73
      int k = idx;
deba@2205
    74
      while (!rep(k)) {
deba@2205
    75
        k = items[k] ;
deba@2205
    76
      }
deba@2205
    77
      while (idx != k) {
deba@2205
    78
        int next = items[idx];
deba@2205
    79
        const_cast<int&>(items[idx]) = k;
deba@2205
    80
        idx = next;
deba@2205
    81
      }
deba@2205
    82
      return k;
deba@2205
    83
    }
beckerjc@483
    84
beckerjc@483
    85
  public:
beckerjc@483
    86
deba@2205
    87
    /// \brief Constructor
deba@2205
    88
    ///
deba@2205
    89
    /// Constructor of the UnionFind class. You should give an item to
deba@2205
    90
    /// integer map which will be used from the data structure. If you
deba@2205
    91
    /// modify directly this map that may cause segmentation fault,
deba@2205
    92
    /// invalid data structure, or infinite loop when you use again
deba@2205
    93
    /// the union-find.
deba@2205
    94
    UnionFind(ItemIntMap& m) : index(m) {}
beckerjc@483
    95
deba@2205
    96
    /// \brief Returns the index of the element's component.
deba@2205
    97
    ///
deba@2205
    98
    /// The method returns the index of the element's component.
deba@2205
    99
    /// This is an integer between zero and the number of inserted elements.
deba@2205
   100
    ///
deba@2205
   101
    int find(const Item& a) {
deba@2205
   102
      return repIndex(index[a]);
beckerjc@483
   103
    }
beckerjc@483
   104
deba@2427
   105
    /// \brief Clears the union-find data structure
deba@2427
   106
    ///
deba@2427
   107
    /// Erase each item from the data structure.
deba@2427
   108
    void clear() {
deba@2427
   109
      items.clear();
deba@2427
   110
    }
deba@2427
   111
deba@2205
   112
    /// \brief Inserts a new element into the structure.
deba@2205
   113
    ///
deba@2205
   114
    /// This method inserts a new element into the data structure. 
deba@2205
   115
    ///
deba@2205
   116
    /// The method returns the index of the new component.
deba@2205
   117
    int insert(const Item& a) {
deba@2205
   118
      int n = items.size();
deba@2205
   119
      items.push_back(-1);
deba@2205
   120
      index.set(a,n);
beckerjc@483
   121
      return n;
beckerjc@483
   122
    }
beckerjc@483
   123
deba@2205
   124
    /// \brief Joining the components of element \e a and element \e b.
deba@2205
   125
    ///
deba@2205
   126
    /// This is the \e union operation of the Union-Find structure. 
deba@2205
   127
    /// Joins the component of element \e a and component of
deba@2205
   128
    /// element \e b. If \e a and \e b are in the same component then
deba@2205
   129
    /// it returns false otherwise it returns true.
deba@2205
   130
    bool join(const Item& a, const Item& b) {
deba@2205
   131
      int ka = repIndex(index[a]);
deba@2205
   132
      int kb = repIndex(index[b]);
beckerjc@483
   133
deba@2205
   134
      if ( ka == kb ) 
beckerjc@483
   135
	return false;
beckerjc@483
   136
deba@2205
   137
      if (items[ka] < items[kb]) {
deba@2205
   138
	items[ka] += items[kb];
deba@2205
   139
	items[kb] = ka;
deba@2205
   140
      } else {
deba@2205
   141
	items[kb] += items[ka];
deba@2205
   142
	items[ka] = kb;
beckerjc@483
   143
      }
beckerjc@483
   144
      return true;
beckerjc@483
   145
    }
beckerjc@483
   146
deba@2205
   147
    /// \brief Returns the size of the component of element \e a.
deba@2205
   148
    ///
deba@2205
   149
    /// Returns the size of the component of element \e a.
deba@2205
   150
    int size(const Item& a) {
deba@2205
   151
      int k = repIndex(index[a]);
deba@2205
   152
      return - items[k];
beckerjc@483
   153
    }
beckerjc@483
   154
beckerjc@483
   155
  };
beckerjc@483
   156
deba@2308
   157
  /// \ingroup auxdat
deba@2308
   158
  ///
deba@2205
   159
  /// \brief A \e Union-Find data structure implementation which
deba@2205
   160
  /// is able to enumerate the components.
deba@2205
   161
  ///
deba@2205
   162
  /// The class implements a \e Union-Find data structure
deba@2205
   163
  /// which is able to enumerate the components and the items in
deba@2205
   164
  /// a component. If you don't need this feature then perhaps it's
deba@2205
   165
  /// better to use the \ref UnionFind class which is more efficient.
deba@2205
   166
  ///
deba@2205
   167
  /// The union operation uses rank heuristic, while
deba@2205
   168
  /// the find operation uses path compression.
deba@2205
   169
  ///
deba@2205
   170
  /// \pre You need to add all the elements by the \ref insert()
deba@2205
   171
  /// method.
deba@2205
   172
  ///
deba@2308
   173
  template <typename _ItemIntMap>
deba@2205
   174
  class UnionFindEnum {
deba@2205
   175
  public:
deba@2205
   176
    
deba@2205
   177
    typedef _ItemIntMap ItemIntMap;
deba@2308
   178
    typedef typename ItemIntMap::Key Item;
deba@2308
   179
deba@2205
   180
  private:
deba@2205
   181
    
deba@2505
   182
    ItemIntMap& index;
deba@2505
   183
deba@2205
   184
    // If the parent stores negative value for an item then that item
deba@2505
   185
    // is root item and it has ~(items[it].parent) component id.  Else
deba@2205
   186
    // the items[it].parent contains the index of the parent.
deba@2205
   187
    //
deba@2505
   188
    // The \c next and \c prev provides the double-linked
deba@2505
   189
    // cyclic list of one component's items.
deba@2205
   190
    struct ItemT {
deba@2205
   191
      int parent;
deba@2205
   192
      Item item;
beckerjc@483
   193
deba@2505
   194
      int next, prev;
deba@2205
   195
    };
beckerjc@483
   196
deba@2205
   197
    std::vector<ItemT> items;
deba@2505
   198
    int firstFreeItem;
beckerjc@483
   199
deba@2505
   200
    struct ClassT {
deba@2505
   201
      int size;
deba@2505
   202
      int firstItem;
deba@2505
   203
      int next, prev;
deba@2505
   204
    };
deba@2505
   205
    
deba@2505
   206
    std::vector<ClassT> classes;
deba@2505
   207
    int firstClass, firstFreeClass;
deba@2505
   208
deba@2505
   209
    int newClass() {
deba@2505
   210
      if (firstFreeClass == -1) {
deba@2505
   211
	int cdx = classes.size();
deba@2505
   212
	classes.push_back(ClassT());
deba@2505
   213
	return cdx;
deba@2505
   214
      } else {
deba@2505
   215
	int cdx = firstFreeClass;
deba@2505
   216
	firstFreeClass = classes[firstFreeClass].next;
deba@2505
   217
	return cdx;
deba@2505
   218
      }
deba@2505
   219
    }
deba@2505
   220
deba@2505
   221
    int newItem() {
deba@2505
   222
      if (firstFreeItem == -1) {
deba@2505
   223
	int idx = items.size();
deba@2505
   224
	items.push_back(ItemT());
deba@2505
   225
	return idx;
deba@2505
   226
      } else {
deba@2505
   227
	int idx = firstFreeItem;
deba@2505
   228
	firstFreeItem = items[firstFreeItem].next;
deba@2505
   229
	return idx;
deba@2505
   230
      }
deba@2505
   231
    }
beckerjc@483
   232
beckerjc@483
   233
deba@2205
   234
    bool rep(int idx) const {
deba@2205
   235
      return items[idx].parent < 0;
beckerjc@483
   236
    }
beckerjc@483
   237
deba@2205
   238
    int repIndex(int idx) const {
deba@2205
   239
      int k = idx;
deba@2205
   240
      while (!rep(k)) {
deba@2205
   241
        k = items[k].parent;
deba@2205
   242
      }
deba@2205
   243
      while (idx != k) {
deba@2205
   244
        int next = items[idx].parent;
deba@2205
   245
        const_cast<int&>(items[idx].parent) = k;
deba@2205
   246
        idx = next;
deba@2205
   247
      }
deba@2205
   248
      return k;
deba@2205
   249
    }
deba@2205
   250
deba@2505
   251
    int classIndex(int idx) const {
deba@2505
   252
      return ~(items[repIndex(idx)].parent);
deba@2505
   253
    }
deba@2505
   254
deba@2505
   255
    void singletonItem(int idx) {
deba@2505
   256
      items[idx].next = idx;
deba@2505
   257
      items[idx].prev = idx;
deba@2505
   258
    }
deba@2505
   259
deba@2505
   260
    void laceItem(int idx, int rdx) {
deba@2505
   261
      items[idx].prev = rdx;
deba@2505
   262
      items[idx].next = items[rdx].next;
deba@2505
   263
      items[items[rdx].next].prev = idx;
deba@2505
   264
      items[rdx].next = idx;
deba@2505
   265
    }
deba@2505
   266
deba@2505
   267
    void unlaceItem(int idx) {
deba@2505
   268
      items[items[idx].prev].next = items[idx].next;
deba@2505
   269
      items[items[idx].next].prev = items[idx].prev;
deba@2505
   270
      
deba@2505
   271
      items[idx].next = firstFreeItem;
deba@2505
   272
      firstFreeItem = idx;
deba@2505
   273
    }
deba@2505
   274
deba@2505
   275
    void spliceItems(int ak, int bk) {
deba@2505
   276
      items[items[ak].prev].next = bk;
deba@2505
   277
      items[items[bk].prev].next = ak;
deba@2505
   278
      int tmp = items[ak].prev;
deba@2505
   279
      items[ak].prev = items[bk].prev;
deba@2505
   280
      items[bk].prev = tmp;
deba@2505
   281
        
deba@2505
   282
    }
deba@2505
   283
deba@2505
   284
    void laceClass(int cls) {
deba@2505
   285
      if (firstClass != -1) {
deba@2505
   286
        classes[firstClass].prev = cls;
deba@2205
   287
      }
deba@2505
   288
      classes[cls].next = firstClass;
deba@2505
   289
      classes[cls].prev = -1;
deba@2505
   290
      firstClass = cls;
deba@2205
   291
    } 
deba@2205
   292
deba@2505
   293
    void unlaceClass(int cls) {
deba@2505
   294
      if (classes[cls].prev != -1) {
deba@2505
   295
        classes[classes[cls].prev].next = classes[cls].next;
deba@2505
   296
      } else {
deba@2505
   297
        firstClass = classes[cls].next;
deba@2505
   298
      }
deba@2505
   299
      if (classes[cls].next != -1) {
deba@2505
   300
        classes[classes[cls].next].prev = classes[cls].prev;
deba@2505
   301
      }
deba@2505
   302
      
deba@2505
   303
      classes[cls].next = firstFreeClass;
deba@2505
   304
      firstFreeClass = cls;
deba@2505
   305
    } 
klao@2003
   306
beckerjc@483
   307
  public:
beckerjc@483
   308
deba@2205
   309
    UnionFindEnum(ItemIntMap& _index) 
deba@2505
   310
      : index(_index), items(), firstFreeItem(-1), 
deba@2505
   311
	firstClass(-1), firstFreeClass(-1) {}
deba@2205
   312
    
deba@2205
   313
    /// \brief Inserts the given element into a new component.
deba@2205
   314
    ///
deba@2205
   315
    /// This method creates a new component consisting only of the
deba@2205
   316
    /// given element.
deba@2205
   317
    ///
deba@2505
   318
    int insert(const Item& item) {
deba@2505
   319
      int idx = newItem();
beckerjc@483
   320
deba@2205
   321
      index.set(item, idx);
beckerjc@483
   322
deba@2505
   323
      singletonItem(idx);
deba@2505
   324
      items[idx].item = item;
deba@2505
   325
deba@2505
   326
      int cdx = newClass();
deba@2505
   327
deba@2505
   328
      items[idx].parent = ~cdx;
deba@2505
   329
deba@2505
   330
      laceClass(cdx);
deba@2505
   331
      classes[cdx].size = 1;
deba@2505
   332
      classes[cdx].firstItem = idx;
deba@2505
   333
deba@2505
   334
      firstClass = cdx;
deba@2205
   335
      
deba@2505
   336
      return cdx;
beckerjc@483
   337
    }
beckerjc@483
   338
deba@2205
   339
    /// \brief Inserts the given element into the component of the others.
deba@2205
   340
    ///
deba@2205
   341
    /// This methods inserts the element \e a into the component of the
deba@2205
   342
    /// element \e comp. 
deba@2505
   343
    void insert(const Item& item, int cls) {
deba@2505
   344
      int rdx = classes[cls].firstItem;
deba@2505
   345
      int idx = newItem();
beckerjc@483
   346
deba@2205
   347
      index.set(item, idx);
deba@2205
   348
deba@2505
   349
      laceItem(idx, rdx);
deba@2205
   350
deba@2505
   351
      items[idx].item = item;
deba@2505
   352
      items[idx].parent = rdx;
deba@2205
   353
deba@2505
   354
      ++classes[~(items[rdx].parent)].size;
beckerjc@483
   355
    }
beckerjc@483
   356
deba@2427
   357
    /// \brief Clears the union-find data structure
deba@2427
   358
    ///
deba@2427
   359
    /// Erase each item from the data structure.
deba@2427
   360
    void clear() {
deba@2427
   361
      items.clear();
deba@2427
   362
      firstClass = -1;
deba@2505
   363
      firstFreeItem = -1;
deba@2427
   364
    }
deba@2427
   365
deba@2505
   366
    /// \brief Finds the component of the given element.
deba@2205
   367
    ///
deba@2505
   368
    /// The method returns the component id of the given element.
deba@2505
   369
    int find(const Item &item) const {
deba@2505
   370
      return ~(items[repIndex(index[item])].parent);
beckerjc@483
   371
    }
beckerjc@483
   372
deba@2205
   373
    /// \brief Joining the component of element \e a and element \e b.
deba@2205
   374
    ///
deba@2205
   375
    /// This is the \e union operation of the Union-Find structure. 
deba@2205
   376
    /// Joins the component of element \e a and component of
deba@2205
   377
    /// element \e b. If \e a and \e b are in the same component then
deba@2505
   378
    /// returns -1 else returns the remaining class.
deba@2505
   379
    int join(const Item& a, const Item& b) {
beckerjc@483
   380
deba@2205
   381
      int ak = repIndex(index[a]);
deba@2205
   382
      int bk = repIndex(index[b]);
beckerjc@483
   383
deba@2205
   384
      if (ak == bk) {
deba@2505
   385
	return -1;
beckerjc@483
   386
      }
beckerjc@483
   387
deba@2505
   388
      int acx = ~(items[ak].parent);
deba@2505
   389
      int bcx = ~(items[bk].parent);
deba@2505
   390
deba@2505
   391
      int rcx;
deba@2505
   392
deba@2505
   393
      if (classes[acx].size > classes[bcx].size) {
deba@2505
   394
	classes[acx].size += classes[bcx].size;
deba@2205
   395
	items[bk].parent = ak;
deba@2505
   396
        unlaceClass(bcx);
deba@2505
   397
	rcx = acx;
deba@2205
   398
      } else {
deba@2505
   399
	classes[bcx].size += classes[acx].size;
deba@2205
   400
	items[ak].parent = bk;
deba@2505
   401
        unlaceClass(acx);
deba@2505
   402
	rcx = bcx;
beckerjc@483
   403
      }
deba@2205
   404
      spliceItems(ak, bk);
beckerjc@483
   405
deba@2505
   406
      return rcx;
beckerjc@483
   407
    }
beckerjc@483
   408
deba@2505
   409
    /// \brief Returns the size of the class.
deba@2205
   410
    ///
deba@2505
   411
    /// Returns the size of the class.
deba@2505
   412
    int size(int cls) const {
deba@2505
   413
      return classes[cls].size;
beckerjc@483
   414
    }
beckerjc@483
   415
deba@2505
   416
    /// \brief Splits up the component. 
deba@2205
   417
    ///
deba@2505
   418
    /// Splitting the component into singleton components (component
deba@2505
   419
    /// of size one).
deba@2505
   420
    void split(int cls) {
deba@2505
   421
      int fdx = classes[cls].firstItem;
deba@2505
   422
      int idx = items[fdx].next;
deba@2505
   423
      while (idx != fdx) {
deba@2505
   424
        int next = items[idx].next;
deba@2505
   425
deba@2505
   426
	singletonItem(idx);
deba@2505
   427
deba@2505
   428
	int cdx = newClass();        
deba@2505
   429
        items[idx].parent = ~cdx;
deba@2505
   430
deba@2505
   431
	laceClass(cdx);
deba@2505
   432
	classes[cdx].size = 1;
deba@2505
   433
	classes[cdx].firstItem = idx;
deba@2205
   434
        
deba@2205
   435
        idx = next;
beckerjc@483
   436
      }
beckerjc@483
   437
deba@2505
   438
      items[idx].prev = idx;
deba@2505
   439
      items[idx].next = idx;
deba@2505
   440
deba@2505
   441
      classes[~(items[idx].parent)].size = 1;
deba@2205
   442
      
beckerjc@483
   443
    }
beckerjc@483
   444
deba@2205
   445
    /// \brief Removes the given element from the structure.
deba@2205
   446
    ///
deba@2205
   447
    /// Removes the element from its component and if the component becomes
deba@2205
   448
    /// empty then removes that component from the component list.
deba@2205
   449
    ///
deba@2205
   450
    /// \warning It is an error to remove an element which is not in
deba@2205
   451
    /// the structure.
deba@2505
   452
    /// \warning This running time of this operation is proportional to the
deba@2505
   453
    /// number of the items in this class.
deba@2505
   454
    void erase(const Item& item) {
deba@2205
   455
      int idx = index[item];
deba@2505
   456
      int fdx = items[idx].next;
deba@2505
   457
deba@2505
   458
      int cdx = classIndex(idx);
deba@2505
   459
      if (idx == fdx) {
deba@2505
   460
	unlaceClass(cdx);
deba@2505
   461
	items[idx].next = firstFreeItem;
deba@2505
   462
	firstFreeItem = idx;
deba@2505
   463
	return;
deba@2505
   464
      } else {
deba@2505
   465
	classes[cdx].firstItem = fdx;
deba@2505
   466
	--classes[cdx].size;
deba@2505
   467
	items[fdx].parent = ~cdx;
deba@2505
   468
deba@2505
   469
	unlaceItem(idx);
deba@2505
   470
	idx = items[fdx].next;
deba@2505
   471
	while (idx != fdx) {
deba@2505
   472
	  items[idx].parent = fdx;
deba@2505
   473
	  idx = items[idx].next;
deba@2505
   474
	}
deba@2205
   475
          
beckerjc@483
   476
      }
beckerjc@483
   477
deba@2506
   478
    }
deba@2506
   479
deba@2506
   480
    /// \brief Gives back a representant item of the component.
deba@2506
   481
    ///
deba@2506
   482
    /// Gives back a representant item of the component.
deba@2506
   483
    Item item(int cls) const {
deba@2506
   484
      return items[classes[cls].firstItem].item;
deba@2506
   485
    }
beckerjc@483
   486
deba@2205
   487
    /// \brief Removes the component of the given element from the structure.
deba@2205
   488
    ///
deba@2205
   489
    /// Removes the component of the given element from the structure.
deba@2205
   490
    ///
deba@2205
   491
    /// \warning It is an error to give an element which is not in the
deba@2205
   492
    /// structure.
deba@2505
   493
    void eraseClass(int cls) {
deba@2505
   494
      int fdx = classes[cls].firstItem;
deba@2505
   495
      unlaceClass(cls);
deba@2505
   496
      items[items[fdx].prev].next = firstFreeItem;
deba@2505
   497
      firstFreeItem = fdx;
deba@2205
   498
    }
beckerjc@483
   499
deba@2205
   500
    /// \brief Lemon style iterator for the representant items.
deba@2205
   501
    ///
deba@2205
   502
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2505
   503
    /// on the ids of the classes.
deba@2205
   504
    class ClassIt {
deba@2205
   505
    public:
deba@2205
   506
      /// \brief Constructor of the iterator
deba@2205
   507
      ///
deba@2205
   508
      /// Constructor of the iterator
deba@2205
   509
      ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
deba@2505
   510
        cdx = unionFind->firstClass;
beckerjc@483
   511
      }
beckerjc@483
   512
deba@2205
   513
      /// \brief Constructor to get invalid iterator
deba@2205
   514
      ///
deba@2205
   515
      /// Constructor to get invalid iterator
deba@2505
   516
      ClassIt(Invalid) : unionFind(0), cdx(-1) {}
deba@2205
   517
      
deba@2205
   518
      /// \brief Increment operator
deba@2205
   519
      ///
deba@2205
   520
      /// It steps to the next representant item.
deba@2205
   521
      ClassIt& operator++() {
deba@2505
   522
        cdx = unionFind->classes[cdx].next;
deba@2205
   523
        return *this;
deba@2205
   524
      }
deba@2205
   525
      
deba@2205
   526
      /// \brief Conversion operator
deba@2205
   527
      ///
deba@2205
   528
      /// It converts the iterator to the current representant item.
deba@2505
   529
      operator int() const {
deba@2505
   530
        return cdx;
beckerjc@483
   531
      }
beckerjc@483
   532
deba@2205
   533
      /// \brief Equality operator
deba@2205
   534
      ///
deba@2205
   535
      /// Equality operator
deba@2205
   536
      bool operator==(const ClassIt& i) { 
deba@2505
   537
        return i.cdx == cdx;
deba@2205
   538
      }
beckerjc@483
   539
deba@2205
   540
      /// \brief Inequality operator
deba@2205
   541
      ///
deba@2205
   542
      /// Inequality operator
deba@2205
   543
      bool operator!=(const ClassIt& i) { 
deba@2505
   544
        return i.cdx != cdx;
klao@2003
   545
      }
beckerjc@483
   546
      
deba@2205
   547
    private:
deba@2205
   548
      const UnionFindEnum* unionFind;
deba@2505
   549
      int cdx;
deba@2205
   550
    };
deba@2205
   551
deba@2205
   552
    /// \brief Lemon style iterator for the items of a component.
deba@2205
   553
    ///
deba@2205
   554
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2205
   555
    /// on the items of a class. By example if you want to iterate on
deba@2205
   556
    /// each items of each classes then you may write the next code.
deba@2205
   557
    ///\code
deba@2205
   558
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
deba@2205
   559
    ///   std::cout << "Class: ";
deba@2205
   560
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
deba@2205
   561
    ///     std::cout << toString(iit) << ' ' << std::endl;
deba@2205
   562
    ///   }
deba@2205
   563
    ///   std::cout << std::endl;
deba@2205
   564
    /// }
deba@2205
   565
    ///\endcode
deba@2205
   566
    class ItemIt {
deba@2205
   567
    public:
deba@2205
   568
      /// \brief Constructor of the iterator
deba@2205
   569
      ///
deba@2205
   570
      /// Constructor of the iterator. The iterator iterates
deba@2205
   571
      /// on the class of the \c item.
deba@2505
   572
      ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
deba@2505
   573
        fdx = idx = unionFind->classes[cls].firstItem;
beckerjc@483
   574
      }
beckerjc@483
   575
deba@2205
   576
      /// \brief Constructor to get invalid iterator
deba@2205
   577
      ///
deba@2205
   578
      /// Constructor to get invalid iterator
deba@2205
   579
      ItemIt(Invalid) : unionFind(0), idx(-1) {}
deba@2205
   580
      
deba@2205
   581
      /// \brief Increment operator
deba@2205
   582
      ///
deba@2205
   583
      /// It steps to the next item in the class.
deba@2205
   584
      ItemIt& operator++() {
deba@2505
   585
        idx = unionFind->items[idx].next;
deba@2505
   586
        if (idx == fdx) idx = -1;
deba@2205
   587
        return *this;
klao@2003
   588
      }
deba@2205
   589
      
deba@2205
   590
      /// \brief Conversion operator
deba@2205
   591
      ///
deba@2205
   592
      /// It converts the iterator to the current item.
deba@2205
   593
      operator const Item&() const {
deba@2205
   594
        return unionFind->items[idx].item;
klao@2003
   595
      }
klao@2003
   596
deba@2205
   597
      /// \brief Equality operator
deba@2205
   598
      ///
deba@2205
   599
      /// Equality operator
deba@2205
   600
      bool operator==(const ItemIt& i) { 
deba@2205
   601
        return i.idx == idx;
klao@2003
   602
      }
klao@2003
   603
deba@2205
   604
      /// \brief Inequality operator
deba@2205
   605
      ///
deba@2205
   606
      /// Inequality operator
deba@2205
   607
      bool operator!=(const ItemIt& i) { 
deba@2205
   608
        return i.idx != idx;
deba@2205
   609
      }
deba@2205
   610
      
deba@2205
   611
    private:
deba@2205
   612
      const UnionFindEnum* unionFind;
deba@2505
   613
      int idx, fdx;
beckerjc@483
   614
    };
beckerjc@483
   615
beckerjc@483
   616
  };
beckerjc@483
   617
deba@2505
   618
  /// \ingroup auxdat
deba@2505
   619
  ///
deba@2505
   620
  /// \brief A \e Extend-Find data structure implementation which
deba@2505
   621
  /// is able to enumerate the components.
deba@2505
   622
  ///
deba@2505
   623
  /// The class implements an \e Extend-Find data structure which is
deba@2505
   624
  /// able to enumerate the components and the items in a
deba@2505
   625
  /// component. The data structure is a simplification of the
deba@2505
   626
  /// Union-Find structure, and it does not allow to merge two components.
deba@2505
   627
  ///
deba@2505
   628
  /// \pre You need to add all the elements by the \ref insert()
deba@2505
   629
  /// method.
deba@2505
   630
  template <typename _ItemIntMap>
deba@2505
   631
  class ExtendFindEnum {
deba@2505
   632
  public:
deba@2505
   633
    
deba@2505
   634
    typedef _ItemIntMap ItemIntMap;
deba@2505
   635
    typedef typename ItemIntMap::Key Item;
deba@2505
   636
deba@2505
   637
  private:
deba@2505
   638
    
deba@2505
   639
    ItemIntMap& index;
deba@2505
   640
deba@2505
   641
    struct ItemT {
deba@2505
   642
      int cls;
deba@2505
   643
      Item item;
deba@2505
   644
      int next, prev;
deba@2505
   645
    };
deba@2505
   646
deba@2505
   647
    std::vector<ItemT> items;
deba@2505
   648
    int firstFreeItem;
deba@2505
   649
deba@2505
   650
    struct ClassT {
deba@2505
   651
      int firstItem;
deba@2505
   652
      int next, prev;
deba@2505
   653
    };
deba@2505
   654
deba@2505
   655
    std::vector<ClassT> classes;
deba@2505
   656
deba@2505
   657
    int firstClass, firstFreeClass;
deba@2505
   658
deba@2505
   659
    int newClass() {
deba@2505
   660
      if (firstFreeClass != -1) {
deba@2505
   661
	int cdx = firstFreeClass;
deba@2505
   662
	firstFreeClass = classes[cdx].next;
deba@2505
   663
	return cdx;
deba@2505
   664
      } else {
deba@2505
   665
	classes.push_back(ClassT());
deba@2505
   666
	return classes.size() - 1;
deba@2505
   667
      }
deba@2505
   668
    }
deba@2505
   669
deba@2505
   670
    int newItem() {
deba@2505
   671
      if (firstFreeItem != -1) {
deba@2505
   672
	int idx = firstFreeItem;
deba@2505
   673
	firstFreeItem = items[idx].next;
deba@2505
   674
	return idx;
deba@2505
   675
      } else {
deba@2505
   676
	items.push_back(ItemT());
deba@2505
   677
	return items.size() - 1;
deba@2505
   678
      }
deba@2505
   679
    }
deba@2505
   680
deba@2505
   681
  public:
deba@2505
   682
deba@2505
   683
    /// \brief Constructor
deba@2505
   684
    ExtendFindEnum(ItemIntMap& _index) 
deba@2505
   685
      : index(_index), items(), firstFreeItem(-1), 
deba@2505
   686
	classes(), firstClass(-1), firstFreeClass(-1) {}
deba@2505
   687
    
deba@2505
   688
    /// \brief Inserts the given element into a new component.
deba@2505
   689
    ///
deba@2505
   690
    /// This method creates a new component consisting only of the
deba@2505
   691
    /// given element.
deba@2505
   692
    int insert(const Item& item) {
deba@2505
   693
      int cdx = newClass();
deba@2505
   694
      classes[cdx].prev = -1;
deba@2505
   695
      classes[cdx].next = firstClass;
deba@2542
   696
      if (firstClass != -1) {
deba@2542
   697
	classes[firstClass].prev = cdx;
deba@2542
   698
      }
deba@2505
   699
      firstClass = cdx;
deba@2505
   700
      
deba@2505
   701
      int idx = newItem();
deba@2505
   702
      items[idx].item = item;
deba@2505
   703
      items[idx].cls = cdx;
deba@2505
   704
      items[idx].prev = idx;
deba@2505
   705
      items[idx].next = idx;
deba@2505
   706
deba@2505
   707
      classes[cdx].firstItem = idx;
deba@2505
   708
deba@2505
   709
      index.set(item, idx);
deba@2505
   710
      
deba@2505
   711
      return cdx;
deba@2505
   712
    }
deba@2505
   713
deba@2505
   714
    /// \brief Inserts the given element into the given component.
deba@2505
   715
    ///
deba@2505
   716
    /// This methods inserts the element \e item a into the \e cls class.
deba@2505
   717
    void insert(const Item& item, int cls) {
deba@2505
   718
      int idx = newItem();
deba@2505
   719
      int rdx = classes[cls].firstItem;
deba@2505
   720
      items[idx].item = item;
deba@2505
   721
      items[idx].cls = cls;
deba@2505
   722
deba@2505
   723
      items[idx].prev = rdx;
deba@2505
   724
      items[idx].next = items[rdx].next;
deba@2505
   725
      items[items[rdx].next].prev = idx;
deba@2505
   726
      items[rdx].next = idx;
deba@2505
   727
deba@2505
   728
      index.set(item, idx);
deba@2505
   729
    }
deba@2505
   730
deba@2505
   731
    /// \brief Clears the union-find data structure
deba@2505
   732
    ///
deba@2505
   733
    /// Erase each item from the data structure.
deba@2505
   734
    void clear() {
deba@2505
   735
      items.clear();
deba@2505
   736
      classes.clear;
deba@2505
   737
      firstClass = firstFreeClass = firstFreeItem = -1;
deba@2505
   738
    }
deba@2505
   739
deba@2505
   740
    /// \brief Gives back the class of the \e item.
deba@2505
   741
    ///
deba@2505
   742
    /// Gives back the class of the \e item.
deba@2505
   743
    int find(const Item &item) const {
deba@2505
   744
      return items[index[item]].cls;
deba@2505
   745
    }
deba@2506
   746
deba@2506
   747
    /// \brief Gives back a representant item of the component.
deba@2506
   748
    ///
deba@2506
   749
    /// Gives back a representant item of the component.
deba@2506
   750
    Item item(int cls) const {
deba@2506
   751
      return items[classes[cls].firstItem].item;
deba@2506
   752
    }
deba@2505
   753
    
deba@2505
   754
    /// \brief Removes the given element from the structure.
deba@2505
   755
    ///
deba@2505
   756
    /// Removes the element from its component and if the component becomes
deba@2505
   757
    /// empty then removes that component from the component list.
deba@2505
   758
    ///
deba@2505
   759
    /// \warning It is an error to remove an element which is not in
deba@2505
   760
    /// the structure.
deba@2505
   761
    void erase(const Item &item) {
deba@2505
   762
      int idx = index[item];
deba@2505
   763
      int cdx = items[idx].cls;
deba@2505
   764
      
deba@2505
   765
      if (idx == items[idx].next) {
deba@2505
   766
	if (classes[cdx].prev != -1) {
deba@2505
   767
	  classes[classes[cdx].prev].next = classes[cdx].next; 
deba@2505
   768
	} else {
deba@2505
   769
	  firstClass = classes[cdx].next;
deba@2505
   770
	}
deba@2505
   771
	if (classes[cdx].next != -1) {
deba@2505
   772
	  classes[classes[cdx].next].prev = classes[cdx].prev; 
deba@2505
   773
	}
deba@2505
   774
	classes[cdx].next = firstFreeClass;
deba@2505
   775
	firstFreeClass = cdx;
deba@2505
   776
      } else {
deba@2505
   777
	classes[cdx].firstItem = items[idx].next;
deba@2505
   778
	items[items[idx].next].prev = items[idx].prev;
deba@2505
   779
	items[items[idx].prev].next = items[idx].next;
deba@2505
   780
      }
deba@2505
   781
      items[idx].next = firstFreeItem;
deba@2505
   782
      firstFreeItem = idx;
deba@2505
   783
	
deba@2505
   784
    }    
deba@2505
   785
deba@2505
   786
    
deba@2505
   787
    /// \brief Removes the component of the given element from the structure.
deba@2505
   788
    ///
deba@2505
   789
    /// Removes the component of the given element from the structure.
deba@2505
   790
    ///
deba@2505
   791
    /// \warning It is an error to give an element which is not in the
deba@2505
   792
    /// structure.
deba@2505
   793
    void eraseClass(int cdx) {
deba@2505
   794
      int idx = classes[cdx].firstItem;
deba@2505
   795
      items[items[idx].prev].next = firstFreeItem;
deba@2505
   796
      firstFreeItem = idx;
deba@2505
   797
deba@2505
   798
      if (classes[cdx].prev != -1) {
deba@2505
   799
	classes[classes[cdx].prev].next = classes[cdx].next; 
deba@2505
   800
      } else {
deba@2505
   801
	firstClass = classes[cdx].next;
deba@2505
   802
      }
deba@2505
   803
      if (classes[cdx].next != -1) {
deba@2505
   804
	classes[classes[cdx].next].prev = classes[cdx].prev; 
deba@2505
   805
      }
deba@2505
   806
      classes[cdx].next = firstFreeClass;
deba@2505
   807
      firstFreeClass = cdx;
deba@2505
   808
    }
deba@2505
   809
deba@2505
   810
    /// \brief Lemon style iterator for the classes.
deba@2505
   811
    ///
deba@2505
   812
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2505
   813
    /// on the ids of classes.
deba@2505
   814
    class ClassIt {
deba@2505
   815
    public:
deba@2505
   816
      /// \brief Constructor of the iterator
deba@2505
   817
      ///
deba@2505
   818
      /// Constructor of the iterator
deba@2505
   819
      ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
deba@2505
   820
        cdx = extendFind->firstClass;
deba@2505
   821
      }
deba@2505
   822
deba@2505
   823
      /// \brief Constructor to get invalid iterator
deba@2505
   824
      ///
deba@2505
   825
      /// Constructor to get invalid iterator
deba@2505
   826
      ClassIt(Invalid) : extendFind(0), cdx(-1) {}
deba@2505
   827
      
deba@2505
   828
      /// \brief Increment operator
deba@2505
   829
      ///
deba@2505
   830
      /// It steps to the next representant item.
deba@2505
   831
      ClassIt& operator++() {
deba@2505
   832
        cdx = extendFind->classes[cdx].next;
deba@2505
   833
        return *this;
deba@2505
   834
      }
deba@2505
   835
      
deba@2505
   836
      /// \brief Conversion operator
deba@2505
   837
      ///
deba@2505
   838
      /// It converts the iterator to the current class id.
deba@2505
   839
      operator int() const {
deba@2505
   840
        return cdx;
deba@2505
   841
      }
deba@2505
   842
deba@2505
   843
      /// \brief Equality operator
deba@2505
   844
      ///
deba@2505
   845
      /// Equality operator
deba@2505
   846
      bool operator==(const ClassIt& i) { 
deba@2505
   847
        return i.cdx == cdx;
deba@2505
   848
      }
deba@2505
   849
deba@2505
   850
      /// \brief Inequality operator
deba@2505
   851
      ///
deba@2505
   852
      /// Inequality operator
deba@2505
   853
      bool operator!=(const ClassIt& i) { 
deba@2505
   854
        return i.cdx != cdx;
deba@2505
   855
      }
deba@2505
   856
      
deba@2505
   857
    private:
deba@2505
   858
      const ExtendFindEnum* extendFind;
deba@2505
   859
      int cdx;
deba@2505
   860
    };
deba@2505
   861
deba@2505
   862
    /// \brief Lemon style iterator for the items of a component.
deba@2505
   863
    ///
deba@2505
   864
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2505
   865
    /// on the items of a class. By example if you want to iterate on
deba@2505
   866
    /// each items of each classes then you may write the next code.
deba@2505
   867
    ///\code
deba@2505
   868
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
deba@2505
   869
    ///   std::cout << "Class: ";
deba@2505
   870
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
deba@2505
   871
    ///     std::cout << toString(iit) << ' ' << std::endl;
deba@2505
   872
    ///   }
deba@2505
   873
    ///   std::cout << std::endl;
deba@2505
   874
    /// }
deba@2505
   875
    ///\endcode
deba@2505
   876
    class ItemIt {
deba@2505
   877
    public:
deba@2505
   878
      /// \brief Constructor of the iterator
deba@2505
   879
      ///
deba@2505
   880
      /// Constructor of the iterator. The iterator iterates
deba@2505
   881
      /// on the class of the \c item.
deba@2505
   882
      ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
deba@2505
   883
        fdx = idx = extendFind->classes[cls].firstItem;
deba@2505
   884
      }
deba@2505
   885
deba@2505
   886
      /// \brief Constructor to get invalid iterator
deba@2505
   887
      ///
deba@2505
   888
      /// Constructor to get invalid iterator
deba@2505
   889
      ItemIt(Invalid) : extendFind(0), idx(-1) {}
deba@2505
   890
      
deba@2505
   891
      /// \brief Increment operator
deba@2505
   892
      ///
deba@2505
   893
      /// It steps to the next item in the class.
deba@2505
   894
      ItemIt& operator++() {
deba@2505
   895
        idx = extendFind->items[idx].next;
deba@2505
   896
	if (fdx == idx) idx = -1;
deba@2505
   897
        return *this;
deba@2505
   898
      }
deba@2505
   899
      
deba@2505
   900
      /// \brief Conversion operator
deba@2505
   901
      ///
deba@2505
   902
      /// It converts the iterator to the current item.
deba@2505
   903
      operator const Item&() const {
deba@2505
   904
        return extendFind->items[idx].item;
deba@2505
   905
      }
deba@2505
   906
deba@2505
   907
      /// \brief Equality operator
deba@2505
   908
      ///
deba@2505
   909
      /// Equality operator
deba@2505
   910
      bool operator==(const ItemIt& i) { 
deba@2505
   911
        return i.idx == idx;
deba@2505
   912
      }
deba@2505
   913
deba@2505
   914
      /// \brief Inequality operator
deba@2505
   915
      ///
deba@2505
   916
      /// Inequality operator
deba@2505
   917
      bool operator!=(const ItemIt& i) { 
deba@2505
   918
        return i.idx != idx;
deba@2505
   919
      }
deba@2505
   920
      
deba@2505
   921
    private:
deba@2505
   922
      const ExtendFindEnum* extendFind;
deba@2505
   923
      int idx, fdx;
deba@2505
   924
    };
deba@2505
   925
deba@2505
   926
  };
beckerjc@483
   927
deba@2548
   928
  /// \ingroup auxdat
deba@2548
   929
  ///
deba@2548
   930
  /// \brief A \e Union-Find data structure implementation which
deba@2548
   931
  /// is able to store a priority for each item and retrieve the minimum of
deba@2548
   932
  /// each class.
deba@2548
   933
  ///
deba@2548
   934
  /// A \e Union-Find data structure implementation which is able to
deba@2548
   935
  /// store a priority for each item and retrieve the minimum of each
deba@2548
   936
  /// class. In addition, it supports the joining and splitting the
deba@2548
   937
  /// components. If you don't need this feature then you makes
deba@2548
   938
  /// better to use the \ref UnionFind class which is more efficient.
deba@2548
   939
  ///
deba@2548
   940
  /// The union-find data strcuture based on a (2, 16)-tree with a
deba@2548
   941
  /// tournament minimum selection on the internal nodes. The insert
deba@2548
   942
  /// operation takes O(1), the find, set, decrease and increase takes
deba@2548
   943
  /// O(log(n)), where n is the number of nodes in the current
deba@2548
   944
  /// component.  The complexity of join and split is O(log(n)*k),
deba@2548
   945
  /// where n is the sum of the number of the nodes and k is the
deba@2548
   946
  /// number of joined components or the number of the components
deba@2548
   947
  /// after the split.
deba@2548
   948
  ///
deba@2548
   949
  /// \pre You need to add all the elements by the \ref insert()
deba@2548
   950
  /// method.
deba@2548
   951
  ///
deba@2548
   952
  template <typename _Value, typename _ItemIntMap, 
deba@2548
   953
            typename _Comp = std::less<_Value> >
deba@2548
   954
  class HeapUnionFind {
deba@2548
   955
  public:
deba@2548
   956
    
deba@2548
   957
    typedef _Value Value;
deba@2548
   958
    typedef typename _ItemIntMap::Key Item;
deba@2548
   959
deba@2548
   960
    typedef _ItemIntMap ItemIntMap;
deba@2548
   961
deba@2548
   962
    typedef _Comp Comp;
deba@2548
   963
deba@2548
   964
  private:
deba@2548
   965
deba@2550
   966
    static const int cmax = 16;
deba@2548
   967
deba@2548
   968
    ItemIntMap& index;
deba@2548
   969
deba@2548
   970
    struct ClassNode {
deba@2548
   971
      int parent;
deba@2548
   972
      int depth;
deba@2548
   973
deba@2548
   974
      int left, right;
deba@2548
   975
      int next, prev;
deba@2548
   976
    };
deba@2548
   977
deba@2548
   978
    int first_class;
deba@2548
   979
    int first_free_class;
deba@2548
   980
    std::vector<ClassNode> classes;
deba@2548
   981
deba@2548
   982
    int newClass() {
deba@2548
   983
      if (first_free_class < 0) {
deba@2548
   984
        int id = classes.size();
deba@2548
   985
        classes.push_back(ClassNode());
deba@2548
   986
        return id;
deba@2548
   987
      } else {
deba@2548
   988
        int id = first_free_class;
deba@2548
   989
        first_free_class = classes[id].next;
deba@2548
   990
        return id;
deba@2548
   991
      }
deba@2548
   992
    }
deba@2548
   993
deba@2548
   994
    void deleteClass(int id) {
deba@2548
   995
      classes[id].next = first_free_class;
deba@2548
   996
      first_free_class = id;
deba@2548
   997
    }
deba@2548
   998
deba@2548
   999
    struct ItemNode {
deba@2548
  1000
      int parent;
deba@2548
  1001
      Item item;
deba@2548
  1002
      Value prio;
deba@2548
  1003
      int next, prev;
deba@2548
  1004
      int left, right;
deba@2548
  1005
      int size;
deba@2548
  1006
    };
deba@2548
  1007
deba@2548
  1008
    int first_free_node;
deba@2548
  1009
    std::vector<ItemNode> nodes;
deba@2548
  1010
deba@2548
  1011
    int newNode() {
deba@2548
  1012
      if (first_free_node < 0) {
deba@2548
  1013
        int id = nodes.size();
deba@2548
  1014
        nodes.push_back(ItemNode());
deba@2548
  1015
        return id;
deba@2548
  1016
      } else {
deba@2548
  1017
        int id = first_free_node;
deba@2548
  1018
        first_free_node = nodes[id].next;
deba@2548
  1019
        return id;
deba@2548
  1020
      }
deba@2548
  1021
    }
deba@2548
  1022
deba@2548
  1023
    void deleteNode(int id) {
deba@2548
  1024
      nodes[id].next = first_free_node;
deba@2548
  1025
      first_free_node = id;
deba@2548
  1026
    }
deba@2548
  1027
deba@2548
  1028
    Comp comp;
deba@2548
  1029
deba@2548
  1030
    int findClass(int id) const {
deba@2548
  1031
      int kd = id;
deba@2548
  1032
      while (kd >= 0) {
deba@2548
  1033
        kd = nodes[kd].parent;
deba@2548
  1034
      }
deba@2548
  1035
      return ~kd;
deba@2548
  1036
    }
deba@2548
  1037
deba@2548
  1038
    int leftNode(int id) const {
deba@2548
  1039
      int kd = ~(classes[id].parent);
deba@2548
  1040
      for (int i = 0; i < classes[id].depth; ++i) {
deba@2548
  1041
        kd = nodes[kd].left;
deba@2548
  1042
      }
deba@2548
  1043
      return kd;
deba@2548
  1044
    }
deba@2548
  1045
deba@2548
  1046
    int nextNode(int id) const {
deba@2548
  1047
      int depth = 0;
deba@2548
  1048
      while (id >= 0 && nodes[id].next == -1) {
deba@2548
  1049
        id = nodes[id].parent;
deba@2548
  1050
        ++depth;
deba@2548
  1051
      }
deba@2548
  1052
      if (id < 0) {
deba@2548
  1053
        return -1;
deba@2548
  1054
      }
deba@2548
  1055
      id = nodes[id].next;
deba@2548
  1056
      while (depth--) {
deba@2548
  1057
        id = nodes[id].left;      
deba@2548
  1058
      }
deba@2548
  1059
      return id;
deba@2548
  1060
    }
deba@2548
  1061
deba@2548
  1062
deba@2548
  1063
    void setPrio(int id) {
deba@2548
  1064
      int jd = nodes[id].left;
deba@2548
  1065
      nodes[id].prio = nodes[jd].prio;
deba@2548
  1066
      nodes[id].item = nodes[jd].item;
deba@2548
  1067
      jd = nodes[jd].next;
deba@2548
  1068
      while (jd != -1) {
deba@2548
  1069
        if (comp(nodes[jd].prio, nodes[id].prio)) {
deba@2548
  1070
          nodes[id].prio = nodes[jd].prio;
deba@2548
  1071
          nodes[id].item = nodes[jd].item;
deba@2548
  1072
        }
deba@2548
  1073
        jd = nodes[jd].next;
deba@2548
  1074
      }
deba@2548
  1075
    }
deba@2548
  1076
deba@2548
  1077
    void push(int id, int jd) {
deba@2548
  1078
      nodes[id].size = 1;
deba@2548
  1079
      nodes[id].left = nodes[id].right = jd;
deba@2548
  1080
      nodes[jd].next = nodes[jd].prev = -1;
deba@2548
  1081
      nodes[jd].parent = id;
deba@2548
  1082
    }
deba@2548
  1083
deba@2548
  1084
    void pushAfter(int id, int jd) {
deba@2548
  1085
      int kd = nodes[id].parent;
deba@2548
  1086
      if (nodes[id].next != -1) {
deba@2548
  1087
        nodes[nodes[id].next].prev = jd;
deba@2548
  1088
        if (kd >= 0) {
deba@2548
  1089
          nodes[kd].size += 1;
deba@2548
  1090
        }
deba@2548
  1091
      } else {
deba@2548
  1092
        if (kd >= 0) {
deba@2548
  1093
          nodes[kd].right = jd;
deba@2548
  1094
          nodes[kd].size += 1;
deba@2548
  1095
        }
deba@2548
  1096
      }
deba@2548
  1097
      nodes[jd].next = nodes[id].next;
deba@2548
  1098
      nodes[jd].prev = id;
deba@2548
  1099
      nodes[id].next = jd;
deba@2548
  1100
      nodes[jd].parent = kd;
deba@2548
  1101
    }
deba@2548
  1102
deba@2548
  1103
    void pushRight(int id, int jd) {
deba@2548
  1104
      nodes[id].size += 1;
deba@2548
  1105
      nodes[jd].prev = nodes[id].right;
deba@2548
  1106
      nodes[jd].next = -1;
deba@2548
  1107
      nodes[nodes[id].right].next = jd;
deba@2548
  1108
      nodes[id].right = jd;
deba@2548
  1109
      nodes[jd].parent = id;
deba@2548
  1110
    }
deba@2548
  1111
deba@2548
  1112
    void popRight(int id) {
deba@2548
  1113
      nodes[id].size -= 1;
deba@2548
  1114
      int jd = nodes[id].right;
deba@2548
  1115
      nodes[nodes[jd].prev].next = -1;
deba@2548
  1116
      nodes[id].right = nodes[jd].prev;
deba@2548
  1117
    }
deba@2548
  1118
deba@2548
  1119
    void splice(int id, int jd) {
deba@2548
  1120
      nodes[id].size += nodes[jd].size;
deba@2548
  1121
      nodes[nodes[id].right].next = nodes[jd].left;
deba@2548
  1122
      nodes[nodes[jd].left].prev = nodes[id].right;
deba@2548
  1123
      int kd = nodes[jd].left;
deba@2548
  1124
      while (kd != -1) {
deba@2548
  1125
        nodes[kd].parent = id;
deba@2548
  1126
        kd = nodes[kd].next;
deba@2548
  1127
      }
deba@2550
  1128
      nodes[id].right = nodes[jd].right;
deba@2548
  1129
    }
deba@2548
  1130
deba@2548
  1131
    void split(int id, int jd) {
deba@2548
  1132
      int kd = nodes[id].parent;
deba@2548
  1133
      nodes[kd].right = nodes[id].prev;
deba@2548
  1134
      nodes[nodes[id].prev].next = -1;
deba@2548
  1135
      
deba@2548
  1136
      nodes[jd].left = id;
deba@2548
  1137
      nodes[id].prev = -1;
deba@2548
  1138
      int num = 0;
deba@2548
  1139
      while (id != -1) {
deba@2548
  1140
        nodes[id].parent = jd;
deba@2548
  1141
        nodes[jd].right = id;
deba@2548
  1142
        id = nodes[id].next;
deba@2548
  1143
        ++num;
deba@2548
  1144
      }      
deba@2548
  1145
      nodes[kd].size -= num;
deba@2548
  1146
      nodes[jd].size = num;
deba@2548
  1147
    }
deba@2548
  1148
deba@2548
  1149
    void pushLeft(int id, int jd) {
deba@2548
  1150
      nodes[id].size += 1;
deba@2548
  1151
      nodes[jd].next = nodes[id].left;
deba@2548
  1152
      nodes[jd].prev = -1;
deba@2548
  1153
      nodes[nodes[id].left].prev = jd;
deba@2548
  1154
      nodes[id].left = jd;
deba@2548
  1155
      nodes[jd].parent = id;
deba@2548
  1156
    }
deba@2548
  1157
deba@2548
  1158
    void popLeft(int id) {
deba@2548
  1159
      nodes[id].size -= 1;
deba@2548
  1160
      int jd = nodes[id].left;
deba@2548
  1161
      nodes[nodes[jd].next].prev = -1;
deba@2548
  1162
      nodes[id].left = nodes[jd].next;
deba@2548
  1163
    }
deba@2548
  1164
deba@2548
  1165
    void repairLeft(int id) {
deba@2548
  1166
      int jd = ~(classes[id].parent);
deba@2548
  1167
      while (nodes[jd].left != -1) {
deba@2548
  1168
	int kd = nodes[jd].left;
deba@2548
  1169
	if (nodes[jd].size == 1) {
deba@2548
  1170
	  if (nodes[jd].parent < 0) {
deba@2548
  1171
	    classes[id].parent = ~kd;
deba@2548
  1172
	    classes[id].depth -= 1;
deba@2548
  1173
	    nodes[kd].parent = ~id;
deba@2548
  1174
	    deleteNode(jd);
deba@2548
  1175
	    jd = kd;
deba@2548
  1176
	  } else {
deba@2548
  1177
	    int pd = nodes[jd].parent;
deba@2548
  1178
	    if (nodes[nodes[jd].next].size < cmax) {
deba@2548
  1179
	      pushLeft(nodes[jd].next, nodes[jd].left);
deba@2632
  1180
              if (less(jd, nodes[jd].next) ||
deba@2632
  1181
		  nodes[jd].item == nodes[pd].item) {
deba@2631
  1182
                nodes[nodes[jd].next].prio = nodes[jd].prio;
deba@2631
  1183
                nodes[nodes[jd].next].item = nodes[jd].item;
deba@2631
  1184
	      }
deba@2548
  1185
	      popLeft(pd);
deba@2548
  1186
	      deleteNode(jd);
deba@2548
  1187
	      jd = pd;
deba@2548
  1188
	    } else {
deba@2548
  1189
	      int ld = nodes[nodes[jd].next].left;
deba@2548
  1190
	      popLeft(nodes[jd].next);
deba@2548
  1191
	      pushRight(jd, ld);
deba@2631
  1192
              if (less(ld, nodes[jd].left) || 
deba@2631
  1193
                  nodes[ld].item == nodes[pd].item) {
deba@2548
  1194
		nodes[jd].item = nodes[ld].item;
deba@2631
  1195
		nodes[jd].prio = nodes[ld].prio;
deba@2548
  1196
	      }
deba@2548
  1197
	      if (nodes[nodes[jd].next].item == nodes[ld].item) {
deba@2548
  1198
		setPrio(nodes[jd].next);
deba@2548
  1199
	      }
deba@2548
  1200
	      jd = nodes[jd].left;
deba@2548
  1201
	    }
deba@2548
  1202
	  }
deba@2548
  1203
	} else {
deba@2548
  1204
	  jd = nodes[jd].left;
deba@2548
  1205
	}
deba@2548
  1206
      }
deba@2548
  1207
    }    
deba@2548
  1208
deba@2548
  1209
    void repairRight(int id) {
deba@2548
  1210
      int jd = ~(classes[id].parent);
deba@2548
  1211
      while (nodes[jd].right != -1) {
deba@2548
  1212
	int kd = nodes[jd].right;
deba@2548
  1213
	if (nodes[jd].size == 1) {
deba@2548
  1214
	  if (nodes[jd].parent < 0) {
deba@2548
  1215
	    classes[id].parent = ~kd;
deba@2548
  1216
	    classes[id].depth -= 1;
deba@2548
  1217
	    nodes[kd].parent = ~id;
deba@2548
  1218
	    deleteNode(jd);
deba@2548
  1219
	    jd = kd;
deba@2548
  1220
	  } else {
deba@2548
  1221
	    int pd = nodes[jd].parent;
deba@2548
  1222
	    if (nodes[nodes[jd].prev].size < cmax) {
deba@2548
  1223
	      pushRight(nodes[jd].prev, nodes[jd].right);
deba@2632
  1224
              if (less(jd, nodes[jd].prev) ||
deba@2632
  1225
		  nodes[jd].item == nodes[pd].item) {
deba@2631
  1226
                nodes[nodes[jd].prev].prio = nodes[jd].prio;
deba@2631
  1227
                nodes[nodes[jd].prev].item = nodes[jd].item;
deba@2631
  1228
	      }
deba@2548
  1229
	      popRight(pd);
deba@2548
  1230
	      deleteNode(jd);
deba@2548
  1231
	      jd = pd;
deba@2548
  1232
	    } else {
deba@2548
  1233
	      int ld = nodes[nodes[jd].prev].right;
deba@2548
  1234
	      popRight(nodes[jd].prev);
deba@2548
  1235
	      pushLeft(jd, ld);
deba@2631
  1236
              if (less(ld, nodes[jd].right) ||
deba@2631
  1237
                  nodes[ld].item == nodes[pd].item) {
deba@2548
  1238
		nodes[jd].item = nodes[ld].item;
deba@2631
  1239
		nodes[jd].prio = nodes[ld].prio;
deba@2548
  1240
	      }
deba@2548
  1241
	      if (nodes[nodes[jd].prev].item == nodes[ld].item) {
deba@2548
  1242
		setPrio(nodes[jd].prev);
deba@2548
  1243
	      }
deba@2548
  1244
	      jd = nodes[jd].right;
deba@2548
  1245
	    }
deba@2548
  1246
	  }
deba@2548
  1247
	} else {
deba@2548
  1248
	  jd = nodes[jd].right;
deba@2548
  1249
	}
deba@2548
  1250
      }
deba@2548
  1251
    }
deba@2548
  1252
deba@2548
  1253
deba@2548
  1254
    bool less(int id, int jd) const {
deba@2548
  1255
      return comp(nodes[id].prio, nodes[jd].prio);
deba@2548
  1256
    }
deba@2548
  1257
deba@2548
  1258
    bool equal(int id, int jd) const {
deba@2548
  1259
      return !less(id, jd) && !less(jd, id);
deba@2548
  1260
    }
deba@2548
  1261
deba@2548
  1262
deba@2548
  1263
  public:
deba@2548
  1264
deba@2548
  1265
    /// \brief Returns true when the given class is alive.
deba@2548
  1266
    ///
deba@2548
  1267
    /// Returns true when the given class is alive, ie. the class is
deba@2548
  1268
    /// not nested into other class.
deba@2548
  1269
    bool alive(int cls) const {
deba@2548
  1270
      return classes[cls].parent < 0;
deba@2548
  1271
    }
deba@2548
  1272
deba@2548
  1273
    /// \brief Returns true when the given class is trivial.
deba@2548
  1274
    ///
deba@2548
  1275
    /// Returns true when the given class is trivial, ie. the class
deba@2548
  1276
    /// contains just one item directly.
deba@2548
  1277
    bool trivial(int cls) const {
deba@2548
  1278
      return classes[cls].left == -1;
deba@2548
  1279
    }
deba@2548
  1280
deba@2548
  1281
    /// \brief Constructs the union-find.
deba@2548
  1282
    ///
deba@2548
  1283
    /// Constructs the union-find.  
deba@2548
  1284
    /// \brief _index The index map of the union-find. The data
deba@2548
  1285
    /// structure uses internally for store references.
deba@2548
  1286
    HeapUnionFind(ItemIntMap& _index) 
deba@2548
  1287
      : index(_index), first_class(-1), 
deba@2548
  1288
	first_free_class(-1), first_free_node(-1) {}
deba@2548
  1289
deba@2548
  1290
    /// \brief Insert a new node into a new component.
deba@2548
  1291
    ///
deba@2548
  1292
    /// Insert a new node into a new component.
deba@2548
  1293
    /// \param item The item of the new node.
deba@2548
  1294
    /// \param prio The priority of the new node.
deba@2548
  1295
    /// \return The class id of the one-item-heap.
deba@2548
  1296
    int insert(const Item& item, const Value& prio) {
deba@2548
  1297
      int id = newNode();
deba@2548
  1298
      nodes[id].item = item;
deba@2548
  1299
      nodes[id].prio = prio;
deba@2548
  1300
      nodes[id].size = 0;
deba@2548
  1301
deba@2548
  1302
      nodes[id].prev = -1;
deba@2548
  1303
      nodes[id].next = -1;
deba@2548
  1304
deba@2548
  1305
      nodes[id].left = -1;
deba@2548
  1306
      nodes[id].right = -1;
deba@2548
  1307
deba@2548
  1308
      nodes[id].item = item;
deba@2548
  1309
      index[item] = id;
deba@2548
  1310
      
deba@2548
  1311
      int class_id = newClass();
deba@2548
  1312
      classes[class_id].parent = ~id;
deba@2548
  1313
      classes[class_id].depth = 0;
deba@2548
  1314
deba@2548
  1315
      classes[class_id].left = -1;
deba@2548
  1316
      classes[class_id].right = -1;
deba@2548
  1317
      
deba@2548
  1318
      if (first_class != -1) {
deba@2548
  1319
        classes[first_class].prev = class_id;
deba@2548
  1320
      }
deba@2548
  1321
      classes[class_id].next = first_class;
deba@2548
  1322
      classes[class_id].prev = -1;
deba@2548
  1323
      first_class = class_id;
deba@2548
  1324
deba@2548
  1325
      nodes[id].parent = ~class_id;
deba@2548
  1326
      
deba@2548
  1327
      return class_id;
deba@2548
  1328
    }
deba@2548
  1329
deba@2548
  1330
    /// \brief The class of the item.
deba@2548
  1331
    ///
deba@2548
  1332
    /// \return The alive class id of the item, which is not nested into
deba@2548
  1333
    /// other classes.
deba@2548
  1334
    ///
deba@2548
  1335
    /// The time complexity is O(log(n)).
deba@2548
  1336
    int find(const Item& item) const {
deba@2548
  1337
      return findClass(index[item]);
deba@2548
  1338
    }
deba@2548
  1339
    
deba@2548
  1340
    /// \brief Joins the classes.
deba@2548
  1341
    ///
deba@2548
  1342
    /// The current function joins the given classes. The parameter is
deba@2548
  1343
    /// an STL range which should be contains valid class ids. The
deba@2548
  1344
    /// time complexity is O(log(n)*k) where n is the overall number
deba@2548
  1345
    /// of the joined nodes and k is the number of classes.
deba@2548
  1346
    /// \return The class of the joined classes.
deba@2548
  1347
    /// \pre The range should contain at least two class ids.
deba@2548
  1348
    template <typename Iterator>
deba@2548
  1349
    int join(Iterator begin, Iterator end) {
deba@2548
  1350
      std::vector<int> cs;
deba@2548
  1351
      for (Iterator it = begin; it != end; ++it) {
deba@2548
  1352
        cs.push_back(*it);
deba@2548
  1353
      }
deba@2548
  1354
deba@2548
  1355
      int class_id = newClass();
deba@2548
  1356
      { // creation union-find
deba@2548
  1357
deba@2548
  1358
        if (first_class != -1) {
deba@2548
  1359
          classes[first_class].prev = class_id;
deba@2548
  1360
        }
deba@2548
  1361
        classes[class_id].next = first_class;
deba@2548
  1362
        classes[class_id].prev = -1;
deba@2548
  1363
        first_class = class_id;
deba@2548
  1364
deba@2548
  1365
        classes[class_id].depth = classes[cs[0]].depth;
deba@2548
  1366
        classes[class_id].parent = classes[cs[0]].parent;
deba@2548
  1367
        nodes[~(classes[class_id].parent)].parent = ~class_id;
deba@2548
  1368
deba@2548
  1369
        int l = cs[0];
deba@2548
  1370
deba@2548
  1371
        classes[class_id].left = l;
deba@2548
  1372
        classes[class_id].right = l;
deba@2548
  1373
deba@2548
  1374
        if (classes[l].next != -1) {
deba@2548
  1375
          classes[classes[l].next].prev = classes[l].prev;
deba@2548
  1376
        }
deba@2548
  1377
        classes[classes[l].prev].next = classes[l].next;
deba@2548
  1378
        
deba@2548
  1379
        classes[l].prev = -1;
deba@2548
  1380
        classes[l].next = -1;
deba@2548
  1381
deba@2548
  1382
        classes[l].depth = leftNode(l);
deba@2548
  1383
        classes[l].parent = class_id;
deba@2548
  1384
        
deba@2548
  1385
      }
deba@2548
  1386
deba@2548
  1387
      { // merging of heap
deba@2548
  1388
        int l = class_id;
deba@2548
  1389
        for (int ci = 1; ci < int(cs.size()); ++ci) {
deba@2548
  1390
          int r = cs[ci];
deba@2548
  1391
          int rln = leftNode(r);
deba@2548
  1392
          if (classes[l].depth > classes[r].depth) {
deba@2548
  1393
            int id = ~(classes[l].parent);
deba@2548
  1394
            for (int i = classes[r].depth + 1; i < classes[l].depth; ++i) {
deba@2548
  1395
              id = nodes[id].right;
deba@2548
  1396
            }
deba@2548
  1397
            while (id >= 0 && nodes[id].size == cmax) {
deba@2548
  1398
              int new_id = newNode();
deba@2548
  1399
              int right_id = nodes[id].right;
deba@2548
  1400
deba@2548
  1401
              popRight(id);
deba@2548
  1402
              if (nodes[id].item == nodes[right_id].item) {
deba@2548
  1403
                setPrio(id);
deba@2548
  1404
              }
deba@2548
  1405
              push(new_id, right_id);
deba@2548
  1406
              pushRight(new_id, ~(classes[r].parent));
deba@2631
  1407
deba@2631
  1408
              if (less(~classes[r].parent, right_id)) {
deba@2631
  1409
                nodes[new_id].item = nodes[~classes[r].parent].item;
deba@2631
  1410
                nodes[new_id].prio = nodes[~classes[r].parent].prio;
deba@2631
  1411
              } else {
deba@2631
  1412
                nodes[new_id].item = nodes[right_id].item;
deba@2631
  1413
                nodes[new_id].prio = nodes[right_id].prio;
deba@2631
  1414
              }
deba@2548
  1415
deba@2548
  1416
              id = nodes[id].parent;
deba@2548
  1417
              classes[r].parent = ~new_id;
deba@2548
  1418
            }
deba@2548
  1419
            if (id < 0) {
deba@2548
  1420
              int new_parent = newNode();
deba@2548
  1421
              nodes[new_parent].next = -1;
deba@2548
  1422
              nodes[new_parent].prev = -1;
deba@2548
  1423
              nodes[new_parent].parent = ~l;
deba@2548
  1424
deba@2548
  1425
              push(new_parent, ~(classes[l].parent));
deba@2548
  1426
              pushRight(new_parent, ~(classes[r].parent));
deba@2548
  1427
              setPrio(new_parent);
deba@2548
  1428
deba@2548
  1429
              classes[l].parent = ~new_parent;
deba@2548
  1430
              classes[l].depth += 1;
deba@2548
  1431
            } else {
deba@2548
  1432
              pushRight(id, ~(classes[r].parent));
deba@2548
  1433
              while (id >= 0 && less(~(classes[r].parent), id)) {
deba@2548
  1434
                nodes[id].prio = nodes[~(classes[r].parent)].prio;
deba@2548
  1435
                nodes[id].item = nodes[~(classes[r].parent)].item;
deba@2548
  1436
                id = nodes[id].parent;
deba@2548
  1437
              }
deba@2548
  1438
            }
deba@2548
  1439
          } else if (classes[r].depth > classes[l].depth) {
deba@2548
  1440
            int id = ~(classes[r].parent);
deba@2548
  1441
            for (int i = classes[l].depth + 1; i < classes[r].depth; ++i) {
deba@2548
  1442
              id = nodes[id].left;
deba@2548
  1443
            }
deba@2548
  1444
            while (id >= 0 && nodes[id].size == cmax) {
deba@2548
  1445
              int new_id = newNode();
deba@2548
  1446
              int left_id = nodes[id].left;
deba@2548
  1447
deba@2548
  1448
              popLeft(id);
deba@2548
  1449
              if (nodes[id].prio == nodes[left_id].prio) {
deba@2548
  1450
                setPrio(id);
deba@2548
  1451
              }
deba@2548
  1452
              push(new_id, left_id);
deba@2548
  1453
              pushLeft(new_id, ~(classes[l].parent));
deba@2631
  1454
deba@2631
  1455
              if (less(~classes[l].parent, left_id)) {
deba@2631
  1456
                nodes[new_id].item = nodes[~classes[l].parent].item;
deba@2631
  1457
                nodes[new_id].prio = nodes[~classes[l].parent].prio;
deba@2631
  1458
              } else {
deba@2631
  1459
                nodes[new_id].item = nodes[left_id].item;
deba@2631
  1460
                nodes[new_id].prio = nodes[left_id].prio;
deba@2631
  1461
              }
deba@2548
  1462
deba@2548
  1463
              id = nodes[id].parent;
deba@2548
  1464
              classes[l].parent = ~new_id;
deba@2548
  1465
deba@2548
  1466
            }
deba@2548
  1467
            if (id < 0) {
deba@2548
  1468
              int new_parent = newNode();
deba@2548
  1469
              nodes[new_parent].next = -1;
deba@2548
  1470
              nodes[new_parent].prev = -1;
deba@2548
  1471
              nodes[new_parent].parent = ~l;
deba@2548
  1472
deba@2548
  1473
              push(new_parent, ~(classes[r].parent));
deba@2548
  1474
              pushLeft(new_parent, ~(classes[l].parent));
deba@2548
  1475
              setPrio(new_parent);
deba@2548
  1476
              
deba@2548
  1477
              classes[r].parent = ~new_parent;
deba@2548
  1478
              classes[r].depth += 1;
deba@2548
  1479
            } else {
deba@2548
  1480
              pushLeft(id, ~(classes[l].parent));
deba@2548
  1481
              while (id >= 0 && less(~(classes[l].parent), id)) {
deba@2548
  1482
                nodes[id].prio = nodes[~(classes[l].parent)].prio;
deba@2548
  1483
                nodes[id].item = nodes[~(classes[l].parent)].item;
deba@2548
  1484
                id = nodes[id].parent;
deba@2548
  1485
              }
deba@2548
  1486
            }
deba@2548
  1487
            nodes[~(classes[r].parent)].parent = ~l;
deba@2548
  1488
            classes[l].parent = classes[r].parent;
deba@2548
  1489
            classes[l].depth = classes[r].depth;
deba@2548
  1490
          } else {
deba@2548
  1491
            if (classes[l].depth != 0 && 
deba@2548
  1492
                nodes[~(classes[l].parent)].size + 
deba@2548
  1493
                nodes[~(classes[r].parent)].size <= cmax) {
deba@2548
  1494
              splice(~(classes[l].parent), ~(classes[r].parent));
deba@2548
  1495
              deleteNode(~(classes[r].parent));
deba@2548
  1496
              if (less(~(classes[r].parent), ~(classes[l].parent))) {
deba@2548
  1497
                nodes[~(classes[l].parent)].prio = 
deba@2548
  1498
                  nodes[~(classes[r].parent)].prio;
deba@2548
  1499
                nodes[~(classes[l].parent)].item = 
deba@2548
  1500
                  nodes[~(classes[r].parent)].item;
deba@2548
  1501
              }
deba@2548
  1502
            } else {
deba@2548
  1503
              int new_parent = newNode();
deba@2548
  1504
              nodes[new_parent].next = nodes[new_parent].prev = -1;
deba@2548
  1505
              push(new_parent, ~(classes[l].parent));
deba@2548
  1506
              pushRight(new_parent, ~(classes[r].parent));
deba@2548
  1507
              setPrio(new_parent);
deba@2548
  1508
            
deba@2548
  1509
              classes[l].parent = ~new_parent;
deba@2548
  1510
              classes[l].depth += 1;
deba@2548
  1511
              nodes[new_parent].parent = ~l;
deba@2548
  1512
            }
deba@2548
  1513
          }
deba@2548
  1514
          if (classes[r].next != -1) {
deba@2548
  1515
            classes[classes[r].next].prev = classes[r].prev;
deba@2548
  1516
          }
deba@2548
  1517
          classes[classes[r].prev].next = classes[r].next;
deba@2548
  1518
deba@2548
  1519
          classes[r].prev = classes[l].right;
deba@2548
  1520
          classes[classes[l].right].next = r;
deba@2548
  1521
          classes[l].right = r;
deba@2548
  1522
          classes[r].parent = l;
deba@2548
  1523
deba@2548
  1524
          classes[r].next = -1;
deba@2548
  1525
          classes[r].depth = rln;
deba@2548
  1526
        }
deba@2548
  1527
      }
deba@2548
  1528
      return class_id;
deba@2548
  1529
    }
deba@2548
  1530
deba@2548
  1531
    /// \brief Split the class to subclasses.
deba@2548
  1532
    ///
deba@2548
  1533
    /// The current function splits the given class. The join, which
deba@2548
  1534
    /// made the current class, stored a reference to the
deba@2548
  1535
    /// subclasses. The \c splitClass() member restores the classes
deba@2548
  1536
    /// and creates the heaps. The parameter is an STL output iterator
deba@2548
  1537
    /// which will be filled with the subclass ids. The time
deba@2548
  1538
    /// complexity is O(log(n)*k) where n is the overall number of
deba@2548
  1539
    /// nodes in the splitted classes and k is the number of the
deba@2548
  1540
    /// classes.
deba@2548
  1541
    template <typename Iterator>
deba@2548
  1542
    void split(int cls, Iterator out) {
deba@2548
  1543
      std::vector<int> cs;
deba@2548
  1544
      { // splitting union-find
deba@2548
  1545
        int id = cls;
deba@2548
  1546
        int l = classes[id].left;
deba@2548
  1547
deba@2548
  1548
        classes[l].parent = classes[id].parent;
deba@2548
  1549
        classes[l].depth = classes[id].depth;
deba@2548
  1550
deba@2548
  1551
        nodes[~(classes[l].parent)].parent = ~l;
deba@2548
  1552
deba@2548
  1553
        *out++ = l;
deba@2548
  1554
deba@2548
  1555
        while (l != -1) {
deba@2548
  1556
          cs.push_back(l);
deba@2548
  1557
          l = classes[l].next;
deba@2548
  1558
        }
deba@2548
  1559
deba@2548
  1560
        classes[classes[id].right].next = first_class;
deba@2548
  1561
        classes[first_class].prev = classes[id].right;
deba@2548
  1562
        first_class = classes[id].left;
deba@2548
  1563
        
deba@2548
  1564
        if (classes[id].next != -1) {
deba@2548
  1565
          classes[classes[id].next].prev = classes[id].prev;
deba@2548
  1566
        }
deba@2548
  1567
        classes[classes[id].prev].next = classes[id].next;
deba@2548
  1568
        
deba@2548
  1569
        deleteClass(id);
deba@2548
  1570
      }
deba@2548
  1571
deba@2548
  1572
      {
deba@2548
  1573
        for (int i = 1; i < int(cs.size()); ++i) {
deba@2548
  1574
          int l = classes[cs[i]].depth;
deba@2548
  1575
          while (nodes[nodes[l].parent].left == l) {
deba@2548
  1576
            l = nodes[l].parent;
deba@2548
  1577
          }
deba@2548
  1578
          int r = l;    
deba@2548
  1579
          while (nodes[l].parent >= 0) {
deba@2548
  1580
            l = nodes[l].parent;
deba@2548
  1581
            int new_node = newNode();
deba@2548
  1582
deba@2548
  1583
            nodes[new_node].prev = -1;
deba@2548
  1584
            nodes[new_node].next = -1;
deba@2548
  1585
deba@2548
  1586
            split(r, new_node);
deba@2548
  1587
            pushAfter(l, new_node);
deba@2548
  1588
            setPrio(l);
deba@2548
  1589
            setPrio(new_node);
deba@2548
  1590
            r = new_node;
deba@2548
  1591
          }
deba@2548
  1592
          classes[cs[i]].parent = ~r;
deba@2548
  1593
          classes[cs[i]].depth = classes[~(nodes[l].parent)].depth;
deba@2548
  1594
          nodes[r].parent = ~cs[i];
deba@2548
  1595
deba@2548
  1596
          nodes[l].next = -1;
deba@2548
  1597
          nodes[r].prev = -1;
deba@2548
  1598
deba@2548
  1599
          repairRight(~(nodes[l].parent));
deba@2548
  1600
          repairLeft(cs[i]);
deba@2548
  1601
          
deba@2548
  1602
          *out++ = cs[i];
deba@2548
  1603
        }
deba@2548
  1604
      }
deba@2548
  1605
    }
deba@2548
  1606
deba@2548
  1607
    /// \brief Gives back the priority of the current item.
deba@2548
  1608
    ///
deba@2548
  1609
    /// \return Gives back the priority of the current item.
deba@2548
  1610
    const Value& operator[](const Item& item) const {
deba@2548
  1611
      return nodes[index[item]].prio;
deba@2548
  1612
    }
deba@2548
  1613
deba@2548
  1614
    /// \brief Sets the priority of the current item.
deba@2548
  1615
    ///
deba@2548
  1616
    /// Sets the priority of the current item.
deba@2548
  1617
    void set(const Item& item, const Value& prio) {
deba@2548
  1618
      if (comp(prio, nodes[index[item]].prio)) {
deba@2548
  1619
        decrease(item, prio);
deba@2548
  1620
      } else if (!comp(prio, nodes[index[item]].prio)) {
deba@2548
  1621
        increase(item, prio);
deba@2548
  1622
      }
deba@2548
  1623
    }
deba@2548
  1624
      
deba@2548
  1625
    /// \brief Increase the priority of the current item.
deba@2548
  1626
    ///
deba@2548
  1627
    /// Increase the priority of the current item.
deba@2548
  1628
    void increase(const Item& item, const Value& prio) {
deba@2548
  1629
      int id = index[item];
deba@2548
  1630
      int kd = nodes[id].parent;
deba@2548
  1631
      nodes[id].prio = prio;
deba@2548
  1632
      while (kd >= 0 && nodes[kd].item == item) {
deba@2548
  1633
        setPrio(kd);
deba@2548
  1634
        kd = nodes[kd].parent;
deba@2548
  1635
      }
deba@2548
  1636
    }
deba@2548
  1637
deba@2548
  1638
    /// \brief Increase the priority of the current item.
deba@2548
  1639
    ///
deba@2548
  1640
    /// Increase the priority of the current item.
deba@2548
  1641
    void decrease(const Item& item, const Value& prio) {
deba@2548
  1642
      int id = index[item];
deba@2548
  1643
      int kd = nodes[id].parent;
deba@2548
  1644
      nodes[id].prio = prio;
deba@2548
  1645
      while (kd >= 0 && less(id, kd)) {
deba@2548
  1646
        nodes[kd].prio = prio;
deba@2548
  1647
        nodes[kd].item = item;
deba@2548
  1648
        kd = nodes[kd].parent;
deba@2548
  1649
      }
deba@2548
  1650
    }
deba@2548
  1651
    
deba@2548
  1652
    /// \brief Gives back the minimum priority of the class.
deba@2548
  1653
    ///
deba@2548
  1654
    /// \return Gives back the minimum priority of the class.
deba@2548
  1655
    const Value& classPrio(int cls) const {
deba@2548
  1656
      return nodes[~(classes[cls].parent)].prio;
deba@2548
  1657
    }
deba@2548
  1658
deba@2548
  1659
    /// \brief Gives back the minimum priority item of the class.
deba@2548
  1660
    ///
deba@2548
  1661
    /// \return Gives back the minimum priority item of the class.
deba@2548
  1662
    const Item& classTop(int cls) const {
deba@2548
  1663
      return nodes[~(classes[cls].parent)].item;
deba@2548
  1664
    }
deba@2548
  1665
deba@2548
  1666
    /// \brief Gives back a representant item of the class.
deba@2548
  1667
    /// 
deba@2548
  1668
    /// The representant is indpendent from the priorities of the
deba@2548
  1669
    /// items. 
deba@2548
  1670
    /// \return Gives back a representant item of the class.
deba@2548
  1671
    const Item& classRep(int id) const {
deba@2548
  1672
      int parent = classes[id].parent;
deba@2548
  1673
      return nodes[parent >= 0 ? classes[id].depth : leftNode(id)].item;
deba@2548
  1674
    }
deba@2548
  1675
deba@2548
  1676
    /// \brief Lemon style iterator for the items of a class.
deba@2548
  1677
    ///
deba@2548
  1678
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2548
  1679
    /// on the items of a class. By example if you want to iterate on
deba@2548
  1680
    /// each items of each classes then you may write the next code.
deba@2548
  1681
    ///\code
deba@2548
  1682
    /// for (ClassIt cit(huf); cit != INVALID; ++cit) {
deba@2548
  1683
    ///   std::cout << "Class: ";
deba@2548
  1684
    ///   for (ItemIt iit(huf, cit); iit != INVALID; ++iit) {
deba@2548
  1685
    ///     std::cout << toString(iit) << ' ' << std::endl;
deba@2548
  1686
    ///   }
deba@2548
  1687
    ///   std::cout << std::endl;
deba@2548
  1688
    /// }
deba@2548
  1689
    ///\endcode
deba@2548
  1690
    class ItemIt {
deba@2548
  1691
    private:
deba@2548
  1692
deba@2548
  1693
      const HeapUnionFind* _huf;
deba@2548
  1694
      int _id, _lid;
deba@2548
  1695
      
deba@2548
  1696
    public:
deba@2548
  1697
deba@2548
  1698
      /// \brief Default constructor 
deba@2548
  1699
      ///
deba@2548
  1700
      /// Default constructor 
deba@2548
  1701
      ItemIt() {}
deba@2548
  1702
deba@2548
  1703
      ItemIt(const HeapUnionFind& huf, int cls) : _huf(&huf) {
deba@2548
  1704
        int id = cls;
deba@2548
  1705
        int parent = _huf->classes[id].parent;
deba@2548
  1706
        if (parent >= 0) {
deba@2548
  1707
          _id = _huf->classes[id].depth;
deba@2548
  1708
          if (_huf->classes[id].next != -1) {
deba@2548
  1709
            _lid = _huf->classes[_huf->classes[id].next].depth;
deba@2548
  1710
          } else {
deba@2548
  1711
            _lid = -1;
deba@2548
  1712
          }
deba@2548
  1713
        } else {
deba@2548
  1714
          _id = _huf->leftNode(id);
deba@2548
  1715
          _lid = -1;
deba@2548
  1716
        } 
deba@2548
  1717
      }
deba@2548
  1718
      
deba@2548
  1719
      /// \brief Increment operator
deba@2548
  1720
      ///
deba@2548
  1721
      /// It steps to the next item in the class.
deba@2548
  1722
      ItemIt& operator++() {
deba@2548
  1723
        _id = _huf->nextNode(_id);
deba@2548
  1724
        return *this;
deba@2548
  1725
      }
deba@2548
  1726
deba@2548
  1727
      /// \brief Conversion operator
deba@2548
  1728
      ///
deba@2548
  1729
      /// It converts the iterator to the current item.
deba@2548
  1730
      operator const Item&() const {
deba@2548
  1731
        return _huf->nodes[_id].item;
deba@2548
  1732
      }
deba@2548
  1733
      
deba@2548
  1734
      /// \brief Equality operator
deba@2548
  1735
      ///
deba@2548
  1736
      /// Equality operator
deba@2548
  1737
      bool operator==(const ItemIt& i) { 
deba@2548
  1738
        return i._id == _id;
deba@2548
  1739
      }
deba@2548
  1740
deba@2548
  1741
      /// \brief Inequality operator
deba@2548
  1742
      ///
deba@2548
  1743
      /// Inequality operator
deba@2548
  1744
      bool operator!=(const ItemIt& i) { 
deba@2548
  1745
        return i._id != _id;
deba@2548
  1746
      }
deba@2548
  1747
deba@2548
  1748
      /// \brief Equality operator
deba@2548
  1749
      ///
deba@2548
  1750
      /// Equality operator
deba@2548
  1751
      bool operator==(Invalid) { 
deba@2548
  1752
        return _id == _lid;
deba@2548
  1753
      }
deba@2548
  1754
deba@2548
  1755
      /// \brief Inequality operator
deba@2548
  1756
      ///
deba@2548
  1757
      /// Inequality operator
deba@2548
  1758
      bool operator!=(Invalid) { 
deba@2548
  1759
        return _id != _lid;
deba@2548
  1760
      }
deba@2548
  1761
      
deba@2548
  1762
    };
deba@2548
  1763
deba@2548
  1764
    /// \brief Class iterator
deba@2548
  1765
    ///
deba@2548
  1766
    /// The iterator stores 
deba@2548
  1767
    class ClassIt {
deba@2548
  1768
    private:
deba@2548
  1769
deba@2548
  1770
      const HeapUnionFind* _huf;
deba@2548
  1771
      int _id;
deba@2548
  1772
deba@2548
  1773
    public:
deba@2548
  1774
deba@2548
  1775
      ClassIt(const HeapUnionFind& huf) 
deba@2548
  1776
        : _huf(&huf), _id(huf.first_class) {}
deba@2548
  1777
deba@2548
  1778
      ClassIt(const HeapUnionFind& huf, int cls) 
deba@2548
  1779
        : _huf(&huf), _id(huf.classes[cls].left) {}
deba@2548
  1780
deba@2548
  1781
      ClassIt(Invalid) : _huf(0), _id(-1) {}
deba@2548
  1782
      
deba@2548
  1783
      const ClassIt& operator++() {
deba@2548
  1784
        _id = _huf->classes[_id].next;
deba@2548
  1785
	return *this;
deba@2548
  1786
      }
deba@2548
  1787
deba@2548
  1788
      /// \brief Equality operator
deba@2548
  1789
      ///
deba@2548
  1790
      /// Equality operator
deba@2548
  1791
      bool operator==(const ClassIt& i) { 
deba@2548
  1792
        return i._id == _id;
deba@2548
  1793
      }
deba@2548
  1794
deba@2548
  1795
      /// \brief Inequality operator
deba@2548
  1796
      ///
deba@2548
  1797
      /// Inequality operator
deba@2548
  1798
      bool operator!=(const ClassIt& i) { 
deba@2548
  1799
        return i._id != _id;
deba@2548
  1800
      }      
deba@2548
  1801
      
deba@2548
  1802
      operator int() const {
deba@2548
  1803
	return _id;
deba@2548
  1804
      }
deba@2548
  1805
            
deba@2548
  1806
    };
deba@2548
  1807
deba@2548
  1808
  };
deba@2548
  1809
beckerjc@483
  1810
  //! @}
beckerjc@483
  1811
alpar@921
  1812
} //namespace lemon
beckerjc@483
  1813
alpar@921
  1814
#endif //LEMON_UNION_FIND_H