| 1 | // -*- C++ -*- // | 
|---|
| 2 | /* | 
|---|
| 3 | Union-Find structure | 
|---|
| 4 |  | 
|---|
| 5 | * Ehhez nagyon fontos, hogy az atadott property map inicializalva legyen | 
|---|
| 6 | * minden szobajovo kulcs ertekre, -1 -es ertekkel! | 
|---|
| 7 |   | 
|---|
| 8 | */ | 
|---|
| 9 | #ifndef UNION_FIND_H | 
|---|
| 10 | #define UNION_FIND_H | 
|---|
| 11 |  | 
|---|
| 12 | #include <vector> | 
|---|
| 13 | //#include <map> | 
|---|
| 14 |  | 
|---|
| 15 |  | 
|---|
| 16 | namespace lemon { | 
|---|
| 17 |    | 
|---|
| 18 |   template <typename Key, typename KeyIntMap> | 
|---|
| 19 |     class UnionFind { | 
|---|
| 20 |     KeyIntMap& pointmap; | 
|---|
| 21 |     struct VectorElementType { | 
|---|
| 22 |       int boss; | 
|---|
| 23 |       int count; | 
|---|
| 24 |       VectorElementType(int _boss, int _count){ | 
|---|
| 25 |         boss = _boss; | 
|---|
| 26 |         count = _count; | 
|---|
| 27 |       } | 
|---|
| 28 |     }; | 
|---|
| 29 |     std::vector<VectorElementType> container; | 
|---|
| 30 |     public: | 
|---|
| 31 |        | 
|---|
| 32 |     UnionFind(KeyIntMap& _pointmap): pointmap(_pointmap){ | 
|---|
| 33 |        | 
|---|
| 34 |     }  | 
|---|
| 35 |      | 
|---|
| 36 |     //Give a component of one point to the structure | 
|---|
| 37 |     int addPoint(Key u){ | 
|---|
| 38 |       int _index = container.size(); | 
|---|
| 39 |       VectorElementType buf(_index,1); | 
|---|
| 40 |       container.push_back(buf); | 
|---|
| 41 |       return _index; | 
|---|
| 42 |     } | 
|---|
| 43 |  | 
|---|
| 44 |      | 
|---|
| 45 |     //Finds the big boss of u | 
|---|
| 46 |     int find(Key u){ | 
|---|
| 47 |       if (pointmap.get(u)==-1){ | 
|---|
| 48 |         int whoami = addPoint(u); | 
|---|
| 49 |         pointmap.set(u, whoami); | 
|---|
| 50 |         return whoami; | 
|---|
| 51 |       } | 
|---|
| 52 |       else{ | 
|---|
| 53 |         int emp = pointmap.get(u); | 
|---|
| 54 |         int boss = container[emp].boss; | 
|---|
| 55 |         while(emp != boss){ | 
|---|
| 56 |           emp = boss; | 
|---|
| 57 |           boss = container[emp].boss; | 
|---|
| 58 |         } | 
|---|
| 59 |         return boss; | 
|---|
| 60 |       } | 
|---|
| 61 |     } | 
|---|
| 62 |  | 
|---|
| 63 |     //Finds u and v in the structures and merges the comopnents, if not equal | 
|---|
| 64 |     bool findAndMerge(Key u,Key v){ | 
|---|
| 65 |       int bu = find(u); | 
|---|
| 66 |       int bv = find(v); | 
|---|
| 67 |       if (bu != bv){ | 
|---|
| 68 |         unio(bu,bv); | 
|---|
| 69 |         return true; | 
|---|
| 70 |       } | 
|---|
| 71 |       else{ | 
|---|
| 72 |         return false; | 
|---|
| 73 |       } | 
|---|
| 74 |     } | 
|---|
| 75 |  | 
|---|
| 76 |     //Merges a into b | 
|---|
| 77 |     void mergeInto(int a, int b){ | 
|---|
| 78 |       container[a].boss = b; | 
|---|
| 79 |       container[b].count +=  container[a].count; | 
|---|
| 80 |     } | 
|---|
| 81 |      | 
|---|
| 82 |     //Makes the union | 
|---|
| 83 |     void unio(int b1, int b2){ | 
|---|
| 84 |       if (container[b1].count>container[b2].count){ | 
|---|
| 85 |         mergeInto(b2,b1); | 
|---|
| 86 |       } | 
|---|
| 87 |       else{ | 
|---|
| 88 |         mergeInto(b1,b2); | 
|---|
| 89 |       } | 
|---|
| 90 |     }//unio | 
|---|
| 91 |   }; | 
|---|
| 92 |    | 
|---|
| 93 | }//namespace lemon | 
|---|
| 94 | #endif | 
|---|