From 07d9190a95ad4d2f03041417d8e73255b889424c Mon Sep 17 00:00:00 2001 From: Sagar Pandya Date: Wed, 28 Oct 2020 17:53:51 +0530 Subject: [PATCH 1/7] Documentation improved --- graph/connected_components_with_dsu.cpp | 86 ++++++++++++++++++------- 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index 50d0c4242..191c2bc88 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -1,45 +1,79 @@ -#include -#include -#include +/** + * @file + * @brief [Disjoint union](https://en.wikipedia.org/wiki/Disjoint_union) + * + * @details + * The Disjoint union is the technique to find connected component in graph efficiently. + * + * ### Algorithm + * In Graph, if you have to find out the number of connected components, there are 2 options + * 1. Use Depth first search + * 2. Disjoint union + * 1st option is inefficient, Disjoint union is the most optimal way to find this. + */ +#include /// for io operations +#include /// for std::set +#include /// for std::vector int number_of_nodes; // denotes number of nodes; -std::vector parent; -std::vector connected_set_size; -void make_set() { // function the initialize every node as it's own parent +std::vector parent; // parent of each node +std::vector connected_set_size; // size of each set +/** + * @brief function the initialize every node as it's own parent + * @returns void + */ +void make_set() { for (int i = 1; i <= number_of_nodes; i++) { parent[i] = i; connected_set_size[i] = 1; } } -// To find the component where following node belongs to -int find_set(int v) { - if (v == parent[v]) { - return v; +/** + * @brief To find the component where following node belongs to + * @param val parent of val should be found + * @return parent of val + */ +int find_set(int val) { + if (val == parent[val]) { + return val; } - return parent[v] = find_set(parent[v]); + return parent[val] = find_set(parent[val]); } +/** + * @brief To join 2 components to belong to one + * @param a 1st component + * @param b 2nd component + * @returns void + */ +void union_sets(int a, int b) { + a = find_set(a); // find the parent of a + b = find_set(b); // find the parent of b -void union_sets(int a, int b) { // To join 2 components to belong to one - a = find_set(a); - b = find_set(b); + // If parents of both nodes are not same, combine them if (a != b) { if (connected_set_size[a] < connected_set_size[b]) { - std::swap(a, b); + std::swap(a, b); // swap both components } - parent[b] = a; - connected_set_size[a] += connected_set_size[b]; + parent[b] = a; // make a node as parent of b node. + connected_set_size[a] += connected_set_size[b]; // sum the size of both as they combined } } - -int no_of_connected_components() { // To find total no of connected components +/** + * @brief To find total no of connected components + * @return Number of connected components + */ +int no_of_connected_components() { std::set temp; // temp set to count number of connected components - for (int i = 1; i <= number_of_nodes; i++) temp.insert(find_set(i)); - return temp.size(); + for (int i = 1; i <= number_of_nodes; i++) + temp.insert(find_set(i)); + return temp.size(); // return the size of temp set } -// All critical/corner cases have been taken care of. -// Input your required values: (not hardcoded) -int main() { +/** + * @brief Test Implementations + * @returns void + */ +static void test() { std::cin >> number_of_nodes; parent.resize(number_of_nodes + 1); connected_set_size.resize(number_of_nodes + 1); @@ -52,5 +86,9 @@ int main() { union_sets(node_a, node_b); } std::cout << no_of_connected_components() << std::endl; +} + +int main() { + test(); // Execute the tests return 0; } From f3e58c0f05cc7107e0a888d5c24617083ffc7671 Mon Sep 17 00:00:00 2001 From: Sagar Pandya Date: Wed, 28 Oct 2020 18:07:01 +0530 Subject: [PATCH 2/7] made find_set method efficient --- graph/connected_components_with_dsu.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index 191c2bc88..c582d6f58 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -7,7 +7,7 @@ * * ### Algorithm * In Graph, if you have to find out the number of connected components, there are 2 options - * 1. Use Depth first search + * 1. Depth first search * 2. Disjoint union * 1st option is inefficient, Disjoint union is the most optimal way to find this. */ @@ -34,10 +34,11 @@ void make_set() { * @return parent of val */ int find_set(int val) { - if (val == parent[val]) { - return val; + while (parent[val] != val) { + parent[val] = parent[parent[val]]; + val = parent[val]; } - return parent[val] = find_set(parent[val]); + return val; } /** * @brief To join 2 components to belong to one From 5f873a7b111555fb803da81816526ac4e7fc7c93 Mon Sep 17 00:00:00 2001 From: Sagar Pandya Date: Wed, 28 Oct 2020 21:17:16 +0530 Subject: [PATCH 3/7] readability improved --- graph/connected_components_with_dsu.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index c582d6f58..cd64a1bb2 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -42,21 +42,21 @@ int find_set(int val) { } /** * @brief To join 2 components to belong to one - * @param a 1st component - * @param b 2nd component + * @param node1 1st component + * @param node2 2nd component * @returns void */ -void union_sets(int a, int b) { - a = find_set(a); // find the parent of a - b = find_set(b); // find the parent of b +void union_sets(int node1, int node2) { + node1 = find_set(node1); // find the parent of node1 + node2 = find_set(node2); // find the parent of node2 // If parents of both nodes are not same, combine them - if (a != b) { - if (connected_set_size[a] < connected_set_size[b]) { - std::swap(a, b); // swap both components + if (node1 != node2) { + if (connected_set_size[node1] < connected_set_size[node2]) { + std::swap(node1, node2); // swap both components } - parent[b] = a; // make a node as parent of b node. - connected_set_size[a] += connected_set_size[b]; // sum the size of both as they combined + parent[node2] = node1; // make node1 as parent of node2. + connected_set_size[node1] += connected_set_size[node2]; // sum the size of both as they combined } } /** From 344be2cb832510dae01e5cf69c59e79bf077ab66 Mon Sep 17 00:00:00 2001 From: Sagar Pandya Date: Fri, 8 Jan 2021 15:11:34 +0530 Subject: [PATCH 4/7] namespaces added datatype changed for big number documentation improved --- graph/connected_components_with_dsu.cpp | 122 +++++++++++++++++------- 1 file changed, 89 insertions(+), 33 deletions(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index 50d0c4242..5317361b2 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -1,56 +1,112 @@ -#include -#include -#include +/** + * @file + * @brief [Disjoint union](https://en.wikipedia.org/wiki/Disjoint_union) + * + * @details + * The Disjoint union is the technique to find connected component in graph efficiently. + * + * ### Algorithm + * In Graph, if you have to find out the number of connected components, there are 2 options + * 1. Depth first search + * 2. Disjoint union + * 1st option is inefficient, Disjoint union is the most optimal way to find this. + */ +#include /// for io operations +#include /// for std::set +#include /// for std::vector -int number_of_nodes; // denotes number of nodes; -std::vector parent; -std::vector connected_set_size; -void make_set() { // function the initialize every node as it's own parent - for (int i = 1; i <= number_of_nodes; i++) { +/** + * @namespace graph + * @brief Graph Algorithms + */ +namespace graph { + +/** + * @namespace disjoint_union + * @brief Function for [Disjoint union] (https://en.wikipedia.org/wiki/Disjoint_union) implementation + */ +namespace disjoint_union { + +int64_t number_of_nodes; // denotes number of nodes +std::vector parent; // parent of each node +std::vector connected_set_size; // size of each set +/** + * @brief function the initialize every node as it's own parent + * @returns void + */ +void make_set() { + for (int64_t i = 1; i <= number_of_nodes; i++) { parent[i] = i; connected_set_size[i] = 1; } } -// To find the component where following node belongs to -int find_set(int v) { - if (v == parent[v]) { - return v; +/** + * @brief To find the component where following node belongs to + * @param val parent of val should be found + * @return parent of val + */ +int64_t find_set(int64_t val) { + while (parent[val] != val) { + parent[val] = parent[parent[val]]; + val = parent[val]; } - return parent[v] = find_set(parent[v]); + return val; } +/** + * @brief To join 2 components to belong to one + * @param node1 1st component + * @param node2 2nd component + * @returns void + */ +void union_sets(int64_t node1, int64_t node2) { + node1 = find_set(node1); // find the parent of node1 + node2 = find_set(node2); // find the parent of node2 -void union_sets(int a, int b) { // To join 2 components to belong to one - a = find_set(a); - b = find_set(b); - if (a != b) { - if (connected_set_size[a] < connected_set_size[b]) { - std::swap(a, b); + // If parents of both nodes are not same, combine them + if (node1 != node2) { + if (connected_set_size[node1] < connected_set_size[node2]) { + std::swap(node1, node2); // swap both components } - parent[b] = a; - connected_set_size[a] += connected_set_size[b]; + parent[node2] = node1; // make node1 as parent of node2. + connected_set_size[node1] += + connected_set_size[node2]; // sum the size of both as they combined } } - -int no_of_connected_components() { // To find total no of connected components - std::set temp; // temp set to count number of connected components - for (int i = 1; i <= number_of_nodes; i++) temp.insert(find_set(i)); - return temp.size(); +/** + * @brief To find total no of connected components + * @return Number of connected components + */ +int64_t no_of_connected_components() { + std::set temp; // temp set to count number of connected components + for (int64_t i = 1; i <= number_of_nodes; i++) temp.insert(find_set(i)); + return temp.size(); // return the size of temp set } - -// All critical/corner cases have been taken care of. -// Input your required values: (not hardcoded) -int main() { +/** + * @brief Test Implementations + * @returns void + */ +static void test() { std::cin >> number_of_nodes; parent.resize(number_of_nodes + 1); connected_set_size.resize(number_of_nodes + 1); make_set(); - int edges = 0; + int64_t edges = 0; std::cin >> edges; // no of edges in the graph while (edges--) { - int node_a = 0, node_b = 0; + int64_t node_a = 0, node_b = 0; std::cin >> node_a >> node_b; union_sets(node_a, node_b); } std::cout << no_of_connected_components() << std::endl; - return 0; } +} // namespace disjoint_union +} // namespace graph + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + graph::disjoint_union::test(); // Execute the tests + return 0; +} \ No newline at end of file From 46b5788298ba69f03538949ab0b56426c25caa9e Mon Sep 17 00:00:00 2001 From: Sagar Pandya Date: Tue, 12 Jan 2021 14:40:27 +0530 Subject: [PATCH 5/7] Readability improved --- graph/connected_components_with_dsu.cpp | 26 ++++++++++++------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index cadcb1105..4ce2de73a 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -11,7 +11,7 @@ * 2. Disjoint union * 1st option is inefficient, Disjoint union is the most optimal way to find this. */ -#include /// for io operations +#include /// for IO operations #include /// for std::set #include /// for std::vector @@ -20,13 +20,11 @@ * @brief Graphical Algorithms */ namespace graph { - /** * @namespace disjoint_union - * @brief Functions for [Disjoint union] (https://en.wikipedia.org/wiki/Disjoint_union) implementation + * @brief Functions for [Disjoint union](https://en.wikipedia.org/wiki/Disjoint_union) implementation */ namespace disjoint_union { - uint32_t number_of_nodes = 0; // denotes number of nodes std::vector parent{}; // parent of each node std::vector connected_set_size{}; // size of each set @@ -81,32 +79,32 @@ uint32_t no_of_connected_components() { for (uint32_t i = 1; i <= number_of_nodes; i++) temp.insert(find_set(i)); return temp.size(); // return the size of temp set } +} // namespace disjoint_union +} // namespace graph /** * @brief Test Implementations * @returns void */ static void test() { - std::cin >> number_of_nodes; - parent.resize(number_of_nodes + 1); - connected_set_size.resize(number_of_nodes + 1); - make_set(); + namespace dsu = graph::disjoint_union; + std::cin >> dsu::number_of_nodes; + dsu::parent.resize(dsu::number_of_nodes + 1); + dsu::connected_set_size.resize(dsu::number_of_nodes + 1); + dsu::make_set(); uint32_t edges = 0; std::cin >> edges; // no of edges in the graph while (edges--) { int64_t node_a = 0, node_b = 0; std::cin >> node_a >> node_b; - union_sets(node_a, node_b); + dsu::union_sets(node_a, node_b); } - std::cout << no_of_connected_components() << std::endl; + std::cout << dsu::no_of_connected_components() << std::endl; } -} // namespace disjoint_union -} // namespace graph - /** * @brief Main function * @returns 0 on exit */ int main() { - graph::disjoint_union::test(); // Execute the tests + test(); // Execute the tests return 0; } From 796c44f99353bf659976f6fde1861ee2b6746e03 Mon Sep 17 00:00:00 2001 From: Sagar Pandya Date: Thu, 14 Jan 2021 20:10:17 +0530 Subject: [PATCH 6/7] author name added and minor documentation fixed --- graph/connected_components_with_dsu.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index 4ce2de73a..e956ada85 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -10,6 +10,9 @@ * 1. Depth first search * 2. Disjoint union * 1st option is inefficient, Disjoint union is the most optimal way to find this. + * + * @author Unknown author + * @author [Sagar Pandya](https://github.com/sagarpandyansit) */ #include /// for IO operations #include /// for std::set @@ -79,8 +82,9 @@ uint32_t no_of_connected_components() { for (uint32_t i = 1; i <= number_of_nodes; i++) temp.insert(find_set(i)); return temp.size(); // return the size of temp set } -} // namespace disjoint_union -} // namespace graph +} // namespace disjoint_union +} // namespace graph + /** * @brief Test Implementations * @returns void @@ -100,6 +104,7 @@ static void test() { } std::cout << dsu::no_of_connected_components() << std::endl; } + /** * @brief Main function * @returns 0 on exit From cb5d854490993a7d882073a5e5323e9634220f10 Mon Sep 17 00:00:00 2001 From: Sagar Pandya <31953933+sagarpandyansit@users.noreply.github.com> Date: Fri, 15 Jan 2021 20:38:15 +0530 Subject: [PATCH 7/7] minor documentation changed Co-authored-by: Ayaan Khan --- graph/connected_components_with_dsu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp index e956ada85..c0194e851 100644 --- a/graph/connected_components_with_dsu.cpp +++ b/graph/connected_components_with_dsu.cpp @@ -20,7 +20,7 @@ /** * @namespace graph - * @brief Graphical Algorithms + * @brief Graph Algorithms */ namespace graph { /**