{"id":1716,"date":"2024-02-24T13:00:00","date_gmt":"2024-02-24T13:00:00","guid":{"rendered":"https:\/\/favtutor.com\/articles\/?p=1716"},"modified":"2024-02-28T06:02:01","modified_gmt":"2024-02-28T06:02:01","slug":"graph-valid-tree","status":"publish","type":"post","link":"https:\/\/favtutor.com\/articles\/graph-valid-tree\/","title":{"rendered":"Check if Given Graph is Tree or Not (C++, Java, Python)"},"content":{"rendered":"\n<p>The Graph is one of the main data structures and the Graph Valid Tree problem is one of the famous problems that involve finding and returning the length of a new string formed after compressing the original one. In this article, we will understand the problem and explore the approach to solving this problem implement code in C++, Java, and Python, and also discuss their time and space complexity.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What is the Graph Valid Tree Problem?<\/strong><\/h2>\n\n\n\n<p><strong>In the Graph Valid Tree problem, we are given n nodes labeled from 0 to n-1 and a list of m undirected edges. We have to find out if we can make any valid tree by using these edges.<\/strong><\/p>\n\n\n\n<p>The tree is a special type of graph which have the following 2 properties:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It is <strong>connected. <\/strong>In simpler terms, we can travel from any vertex in the graph to any other vertex by following the edges. There are no isolated vertices within a connected graph<\/li>\n\n\n\n<li>It has <strong>no cycle. <\/strong>A graph that does not have a cycle means that there are no closed loops in the graphs.<\/li>\n<\/ul>\n\n\n\n<p>Let us discuss this problem with an example.<\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color has-background has-link-color wp-elements-e9e1b651a7275b39deb5cd7978c31cc4\" style=\"background-color:#fedcba\"><code>n=5\nedges= &#91; &#91;0, 1], &#91;0, 2], &#91;0, 3], &#91;1, 4] ]<\/code><\/pre>\n\n\n\n<p>When we try to plot all these edges then we get the graph shown below.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/-XzfE40fO80ybL6ccp6akOqlW22cYJUJvWmWTC7OQRGGtzyuzbyXdMx3kxaUaoFk4aiCPJPwROmUqI7Yi6JzlYX1pLmdmg9TQ6Xi_TVblKNBm9xagx1D8bs-KHrkTy6GWbDvwXMRHngK9pHPEkTn0LQ\" alt=\"Example\"\/><\/figure>\n<\/div>\n\n\n<p>In the above image, we can see that there is no cycle and the graph is connected so the above graph is a valid tree.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>BFS Approach<\/strong><\/h2>\n\n\n\n<p>We have to check if the graph is connected and does not contain a cycle for a graph to be a valid tree. For this, we will make a visited array of nodes(visi) and we will do two things simultaneously:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, we will calculate the number of components. If the number of components is greater than 1 then the graph is not connected thus we will return false.<\/li>\n\n\n\n<li>Second, to check if there exists a cycle in the graph, we can perform a <a href=\"https:\/\/favtutor.com\/blogs\/breadth-first-search-python\">Breadth-First Search (BFS) traversal<\/a> starting from any vertex. During the traversal, we mark each visited vertex and maintain a parent array(parent) to keep track of the parent vertex for each visited vertex. If we encounter a vertex that is already visited but is not the parent of the current vertex, then there exists a cycle in the graph and we will return false.<\/li>\n<\/ul>\n\n\n\n<p>Here is a simple illustration of that example:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We will start from vertex 0 and run BFS on it. We will mark the visit of 0 as true and the parent of 0 as -1 as 0 is our entry vertex. We will also maintain a queue and push 0 in it.<br><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/W8qo_OngAAzoeOzmkAgTvwNLHVogIUpI0O5GQ5fbtNaYBVGauxEw_HtLUnkWbiufPBHJ3BI9xeZFroS6PgP009D1hziGFfjxCiHqq75OvM2ZtCZ0cRxqD8xvvjzGAMxRq9LwENh6LiT-CoNXyWMEIXE\" alt=\"Initialize data structures\"\/><\/figure>\n<\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>Now we will take and pop the front element of the queue i.e. 0 and traverse to the vertex connected to 0 one by one.\n<ul class=\"wp-block-list\">\n<li>We will move to vertex 1 (it has not been visited earlier) and mark visited of 1 as true and the parent of 1 will be 0. Now we will push 1 to our queue.<\/li>\n\n\n\n<li>&nbsp;We will move to vertex 2 (it has not been visited earlier) and mark visited of 2 as true and the parent of 2 will be 0. Now we will push 2 to our queue.&nbsp;<\/li>\n\n\n\n<li>We will move to vertex 3 (it has not been visited earlier) and mark the visited of 3 as true and the parent of 3 will be 0. Now we will push 3 to our queue.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/o8-jd7wUNnGzNqIuLlR7l5C_0SmrdWq5LnXs9t4RfA0XhszJjuRnqazxfowHuI2jlMEYwwq9UJQlPzqUwE2DBxwxB4PjMT2jM5RG_r5tqVfHBFt9dRnxKa65Io5Knn7auXUuO8zLoLNRPtqcZ5I1PQ4\" alt=\"Iterate for 1, 2, 3\"\/><\/figure>\n<\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>Now we will take and pop the front element of the queue i.e. 1 and traverse to vertex connected to 1 one by one.\n<ul class=\"wp-block-list\">\n<li>We will move to vertex 4 (it has not been visited earlier) and mark the visited of 4 as true and the parent of 4 will be 1. Now we will push 4 to our queue.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/lbRf8pylDCZjn8d_BkD4zusLgoVgYp8xH58Uw72A_NzCmlcUH6qwVs3WK8oC3Pb7z9NQv-kUjtFjOm7CfX0YWJm-PRbGpoP7qIZBrxy8QLMZPUkAdqJ879yZY2mZN0EUREjZWV51in2D6QYJAFL19sw\" alt=\"Iterate for 4\"\/><\/figure>\n<\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>Now we will again take and pop the front element of the queue i.e. 2 and traverse to vertex connected to 2 one by one. There is no vertex connected to 2.<\/li>\n\n\n\n<li>Similarly, we will do this for vertex 3,4 and our queue will become empty.<\/li>\n\n\n\n<li>By starting from vertex 0 we have traversed all nodes without revisiting any node which means that there is only one component in the graph and no cycle is present as no node was revisited.<\/li>\n<\/ul>\n\n\n\n<p>Thus we can conclude that the given graph is a valid tree.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>C++ Code<\/strong><\/h3>\n\n\n\n<p>Here is the C++ program to check if the given graph is a tree or not:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;language&quot;:&quot;C++&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">#include &lt;bits\/stdc++.h&gt;  \/\/ Include necessary libraries\n\nusing namespace std;\n\n\/\/ Function to check if there is a cycle starting from node 'i'\nbool cyclic(unordered_map&lt;int, list&lt;int&gt;&gt;&amp; adj, unordered_map&lt;int, bool&gt;&amp; vis, int i) {\n    unordered_map&lt;int, int&gt; parent;  \/\/ Map to keep track of parent nodes\n    parent[i] = -1;  \/\/ Set parent of 'i' as -1\n    vis[i] = true;  \/\/ Mark 'i' as visited\n    queue&lt;int&gt; q;  \/\/ Create a queue for BFS\n    q.push(i);  \/\/ Push 'i' to the queue\n\n    while (!q.empty()) {  \/\/ While the queue is not empty\n        int t = q.front();  \/\/ Get the front of the queue\n        q.pop();  \/\/ Pop the front element\n\n        \/\/ Traverse through all adjacent nodes of 't'\n        for (auto j : adj[t]) {\n            if (vis[j] &amp;&amp; parent[t] != j) {  \/\/ If 'j' is already visited and not the parent of 't'\n                return true;  \/\/ There is a cycle\n            } else if (!vis[j]) {  \/\/ If 'j' is not visited\n                q.push(j);  \/\/ Push 'j' to the queue\n                vis[j] = true;  \/\/ Mark 'j' as visited\n                parent[j] = t;  \/\/ Set parent of 'j' as 't'\n            }\n        }\n    }\n    return false;  \/\/ No cycle found\n}\n\n\/\/ Function to check if the graph is connected and acyclic\nbool checkgraph(vector&lt;vector&lt;int&gt;&gt; edges, int n, int m) {\n    unordered_map&lt;int, list&lt;int&gt;&gt; adj;  \/\/ Adjacency list representation of the graph\n\n    \/\/ Construct the adjacency list from the given edges\n    for (int i = 0; i &lt; edges.size(); i++) {\n        int u = edges[i][0];\n        int v = edges[i][1];\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    unordered_map&lt;int, bool&gt; vis;  \/\/ Map to keep track of visited nodes\n    int comp = 0;  \/\/ Counter for connected components\n\n    \/\/ Iterate through all nodes\n    for (int i = 0; i &lt; n; i++) {\n        if (!vis[i]) {  \/\/ If 'i' is not visited\n            comp++;  \/\/ Increment connected components counter\n            if (comp &gt; 1) {\n                return false;  \/\/ If more than one component, graph is not connected\n            }\n            if (cyclic(adj, vis, i)) {  \/\/ Check for cycles starting from 'i'\n                return false;  \/\/ If cycle found, graph is not acyclic\n            }\n        }\n    }\n    return true;  \/\/ Graph is connected and acyclic\n}\n\nint main() {\n    int n = 5;  \/\/ Number of nodes\n    int m = 4;  \/\/ Number of edges\n\n    \/\/ List of edges\n    vector&lt;vector&lt;int&gt;&gt; edges = {{0, 1}, {0, 2}, {0, 3}, {1, 4}};\n\n    \/\/ Check if the graph is connected and acyclic, and print the result\n    cout &lt;&lt; boolalpha &lt;&lt; checkgraph(edges, n, m) &lt;&lt; endl;\n\n    return 0;\n}<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Python Code<\/strong><\/h3>\n\n\n\n<p>Here is the Python code for this purpose:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;language&quot;:&quot;Python&quot;,&quot;modeName&quot;:&quot;python&quot;}\">from collections import defaultdict, deque\n\n# Function to check if there is a cycle starting from node 'i'\ndef cyclic(adj, vis, i):\n    parent = {}  # Dictionary to keep track of parent nodes\n    parent[i] = -1  # Set parent of 'i' as -1\n    vis[i] = True  # Mark 'i' as visited\n    q = deque()  # Create a deque for BFS\n    q.append(i)  # Append 'i' to the deque\n\n    while q:  # While the deque is not empty\n        t = q.popleft()  # Pop the leftmost element\n        for j in adj[t]:  # Traverse through all adjacent nodes of 't'\n            visited = vis.get(j)\n            if visited is not None and visited and parent.get(t) != j:  # If 'j' is already visited and not the parent of 't'\n                return True  # There is a cycle\n            elif visited is None:  # If 'j' is not visited\n                q.append(j)  # Append 'j' to the deque\n                vis[j] = True  # Mark 'j' as visited\n                parent[j] = t  # Set parent of 'j' as 't'\n    return False  # No cycle found\n\n# Function to check if the graph is connected and acyclic\ndef check_graph(edges, n, m):\n    adj = defaultdict(list)  # Default dictionary for adjacency list representation of the graph\n\n    # Construct the adjacency list from the given edges\n    for u, v in edges:\n        adj[u].append(v)\n        adj[v].append(u)\n\n    vis = {}  # Dictionary to keep track of visited nodes\n    comp = 0  # Counter for connected components\n\n    # Iterate through all nodes\n    for i in range(n):\n        if i not in vis:  # If 'i' is not visited\n            comp += 1  # Increment connected components counter\n            if comp &gt; 1:\n                return False  # If more than one component, graph is not connected\n            if cyclic(adj, vis, i):  # Check for cycles starting from 'i'\n                return False  # If cycle found, graph is not acyclic\n    return True  # Graph is connected and acyclic\n\n# Main function\ndef main():\n    n = 5  # Number of nodes\n    m = 4  # Number of edges\n\n    # List of edges\n    edges = [[0, 1], [0, 2], [0, 3], [1, 4]]\n\n    # Check if the graph is connected and acyclic, and print the result\n    print(check_graph(edges, n, m))\n\nif __name__ == &quot;__main__&quot;:\n    main()<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Java Code<\/strong><\/h3>\n\n\n\n<p>We can implement the BFS approach in Java as well:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;language&quot;:&quot;Java&quot;,&quot;modeName&quot;:&quot;java&quot;}\">import java.util.*;\n\npublic class GraphCycle {\n\n    \/\/ Function to check if there is a cycle starting from node 'i'\n    public static boolean cyclic(Map&lt;Integer, List&lt;Integer&gt;&gt; adj, Map&lt;Integer, Boolean&gt; vis, int i) {\n        Map&lt;Integer, Integer&gt; parent = new HashMap&lt;&gt;(); \/\/ Map to keep track of parent nodes\n        parent.put(i, -1); \/\/ Set parent of 'i' as -1\n        vis.put(i, true); \/\/ Mark 'i' as visited\n        Queue&lt;Integer&gt; q = new LinkedList&lt;&gt;(); \/\/ Create a queue for BFS\n        q.add(i); \/\/ Add 'i' to the queue\n\n        while (!q.isEmpty()) { \/\/ While the queue is not empty\n            int t = q.poll(); \/\/ Poll the front element\n            for (int j : adj.get(t)) { \/\/ Iterate through all adjacent nodes of 't'\n                Boolean visited = vis.get(j); \/\/ Get the value and check for null\n                if (visited != null &amp;&amp; visited &amp;&amp; !Objects.equals(parent.get(t), j)) { \/\/ If 'j' is already visited and not the parent of 't'\n                    return true; \/\/ There is a cycle\n                } else if (visited == null) { \/\/ If 'j' is not visited\n                    q.add(j); \/\/ Add 'j' to the queue\n                    vis.put(j, true); \/\/ Mark 'j' as visited\n                    parent.put(j, t); \/\/ Set parent of 'j' as 't'\n                }\n            }\n        }\n        return false; \/\/ No cycle found\n    }\n\n    \/\/ Function to check if the graph is connected and acyclic\n    public static boolean checkGraph(List&lt;List&lt;Integer&gt;&gt; edges, int n, int m) {\n        Map&lt;Integer, List&lt;Integer&gt;&gt; adj = new HashMap&lt;&gt;(); \/\/ Adjacency list representation of the graph\n\n        \/\/ Construct the adjacency list from the given edges\n        for (List&lt;Integer&gt; edge : edges) {\n            int u = edge.get(0);\n            int v = edge.get(1);\n            adj.computeIfAbsent(u, k -&gt; new ArrayList&lt;&gt;()).add(v);\n            adj.computeIfAbsent(v, k -&gt; new ArrayList&lt;&gt;()).add(u);\n        }\n\n        Map&lt;Integer, Boolean&gt; vis = new HashMap&lt;&gt;(); \/\/ Map to keep track of visited nodes\n        int comp = 0; \/\/ Counter for connected components\n\n        \/\/ Iterate through all nodes\n        for (int i = 0; i &lt; n; i++) {\n            if (!vis.containsKey(i)) { \/\/ If 'i' is not visited\n                comp++; \/\/ Increment connected components counter\n                if (comp &gt; 1) {\n                    return false; \/\/ If more than one component, graph is not connected\n                }\n                if (cyclic(adj, vis, i)) { \/\/ Check for cycles starting from 'i'\n                    return false; \/\/ If cycle found, graph is not acyclic\n                }\n            }\n        }\n        return true; \/\/ Graph is connected and acyclic\n    }\n\n    public static void main(String[] args) {\n        int n = 5; \/\/ Number of nodes\n        int m = 4; \/\/ Number of edges\n\n        List&lt;List&lt;Integer&gt;&gt; edges = new ArrayList&lt;&gt;(); \/\/ List of edges\n        edges.add(Arrays.asList(0, 1));\n        edges.add(Arrays.asList(0, 2));\n        edges.add(Arrays.asList(0, 3));\n        edges.add(Arrays.asList(1, 4));\n\n        \/\/ Check if the graph is connected and acyclic, and print the result\n        System.out.println(checkGraph(edges, n, m));\n    }\n}<\/pre><\/div>\n\n\n\n<p><strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color has-background has-link-color wp-elements-d0c1719f8e0cd3a4057dc3dcdb057c20\" style=\"background-color:#fedcba\"><code>true<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Complexity Analysis<\/strong><\/h3>\n\n\n\n<p><strong>The time complexity for the to check if the given graph is a tree or not using the BFS approach is O(n + m).\u00a0<\/strong><\/p>\n\n\n\n<p>The space complexity is dominated by the space used for the adjacency list and the visited map. The adjacency list requires O(m + n) space because there are n vertices and m edges. The visited map (vis) and parent map inside the cyclic function both require O(n) space. Therefore, the overall space complexity is O(m + n).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>In conclusion, the BFS approach stands out as the most efficient solution for the Graph Valid tree leetcode problem, providing a balance between simplicity and performance. The use of a queue for BFS traversal and visited and parent mappings minimizes time complexity to O(n + m) while maintaining O(m + n) space complexity. This approach is recommended for larger datasets where performance is crucial.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to check if a given graph is a tree or not using the BFS approach, with implementation in C++, Java and Python.<\/p>\n","protected":false},"author":12,"featured_media":1719,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jnews-multi-image_gallery":[],"jnews_single_post":null,"jnews_primary_category":{"id":"","hide":""},"footnotes":""},"categories":[7],"tags":[14,78,15],"class_list":["post-1716","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-data-structures-algorithms","tag-dsa","tag-graph","tag-leetcode"],"_links":{"self":[{"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/posts\/1716","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/comments?post=1716"}],"version-history":[{"count":3,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/posts\/1716\/revisions"}],"predecessor-version":[{"id":2015,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/posts\/1716\/revisions\/2015"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/media\/1719"}],"wp:attachment":[{"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/media?parent=1716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/categories?post=1716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/favtutor.com\/articles\/wp-json\/wp\/v2\/tags?post=1716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}