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