/** * @file * @brief [DSU (Disjoint sets)](https://en.wikipedia.org/wiki/Disjoint-set-data_structure) * @details * It is a very powerful data structure that keeps track of different * clusters(sets) of elements, these sets are disjoint(doesnot have a common element). * Disjoint sets uses cases : for finding connected components in a graph, * used in Kruskal's algorithm for finding Minimum Spanning tree. * Operations that can be performed: * 1) UnionSet(i,j): add(element i and j to the set) * 2) findSet(i): returns the representative of the set to which i belogngs to. * 3) get_max(i),get_min(i) : returns the maximum and minimum * Below is the class-based approach which uses the heuristic of path compression. * Using path compression in findSet(i),we are able to get to the representative of i * in O(1) time. * @author [AayushVyasKIIT](https://github.com/AayushVyasKIIT) * @see dsu_union_rank.cpp */ #include /// for IO operations #include /// for std::vector #include /// for assert using std::cout; using std::endl; using std::vector; /** * @brief Disjoint sets union data structure, class based representation. * @param n number of elements */ class dsu{ private: vector p; /// depth; /// setSize;/// maxElement;/// minElement;/// depth[y]){ std::swap(x,y); } //making the shallower root's parent the deeper root p[x] = y; //if same depth then increase one's depth if(depth[x] == depth[y]){ depth[y]++; } //total size of the resultant set. setSize[y] += setSize[x]; //changing the maximum elements maxElement[y] = std::max(maxElement[x],maxElement[y]); minElement[y] = std::min(minElement[x],minElement[y]); } /** * @brief A utility function which check whether i and j belongs to * same set or not * @param i element of some set * @param j element of some set * @returns `true` if element `i` and `j` ARE in the same set * @returns `false` if element `i` and `j` are NOT in same set */ bool isSame(uint64_t i,uint64_t j){ if(findSet(i) == findSet(j)){ return true; } return false; } /** * @brief prints the minimum, maximum and size of the set to which i belongs to * @param i element of some set * @returns void */ vector get(uint64_t i){ vector ans; ans.push_back(get_min(i)); ans.push_back(get_max(i)); ans.push_back(size(i)); return ans; } /** * @brief A utility function that returns the size of the set to which i belongs to * @param i element of some set * @returns size of the set to which i belongs to */ uint64_t size(uint64_t i){ return setSize[findSet(i)]; } /** * @brief A utility function that returns the max element of the set to which i belongs to * @param i element of some set * @returns maximum of the set to which i belongs to */ uint64_t get_max(uint64_t i){ return maxElement[findSet(i)]; } /** * @brief A utility function that returns the min element of the set to which i belongs to * @param i element of some set * @returns minimum of the set to which i belongs to */ uint64_t get_min(uint64_t i){ return minElement[findSet(i)]; } }; /** * @brief Self-implementation Test case #1 * @returns void */ static void test1() { /* the minimum, maximum and size of the set*/ uint64_t n = 10;///< number of items dsu d(n+1);///< object of class disjoint sets //set 1 d.UnionSet(1,2); //performs union operation on 1 and 2 d.UnionSet(1,4); //performs union operation on 1 and 4 vector ans = {1,4,3}; for(uint64_t i=0;i ans = {3,7,4}; for(uint64_t i=0;i