lemon/unionfind.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 875 07ec2b52e53d
child 1092 dceba191c00d
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

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