Open In App

Disjoint Set Union on Trees

Last Updated : 05 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a tree and weights of nodes. Weights are non-negative integers. Task is to find maximum size of a subtree of a given tree such that all nodes are even in weights.

Prerequisite : Disjoint Set Union

Examples : 

Input : Number of nodes = 7
        Weights of nodes = 1 2 6 4 2 0 3
        Edges = (1, 2), (1, 3), (2, 4), 
                (2, 5), (4, 6), (6, 7)
Output : Maximum size of the subtree 
with even weighted nodes = 4 
Explanation : 
Subtree of nodes {2, 4, 5, 6} gives the maximum size.

Input : Number of nodes = 6
        Weights of nodes = 2 4 0 2 2 6
        Edges = (1, 2), (2, 3), (3, 4), 
                (4, 5), (1, 6)
Output : Maximum size of the subtree
with even weighted nodes = 6
Explanation : 
The given tree gives the maximum size.

Approach: 

We can find solution by simply running DFS on tree. DFS solution gives us answer in O(n). But, how can we use DSU for this problem? 
We first iterate through all edges. If both nodes are even in weights, we make union of them. Set of nodes with maximum size is the answer. If we use union-find with path compression then time complexity is O(n).

Below is the implementation of above approach :  

C++




// CPP code to find maximum subtree such
// that all nodes are even in weight
#include<bits/stdc++.h>
 
using namespace std;
 
#define N 100010
 
// Structure for Edge
struct Edge
{
    int u, v;
};
 
/*
    'id': stores parent of a node.
    'sz': stores size of a DSU tree.
*/
int id[N], sz[N];
 
// Function to assign root
int Root(int idx)
{
    int i = idx;
     
    while(i != id[i])
        id[i] = id[id[i]], i = id[i];
     
    return i;
}
 
// Function to find Union
void Union(int a, int b)
{
    int i = Root(a), j = Root(b);
     
    if (i != j)
    {
        if(sz[i] >= sz[j])
        {
            id[j] = i, sz[i] += sz[j];
            sz[j] = 0;
        }
        else
        {
            id[i] = j, sz[j] += sz[i];
            sz[i] = 0;
        }
    }
}
 
// Utility function for Union
void UnionUtil(struct Edge e[], int W[], int q)
{
 
    for(int i = 0; i < q; i++)
    {
        // Edge between 'u' and 'v'
        int u, v;
        u = e[i].u, v = e[i].v;
 
        // 0-indexed nodes
        u--, v--;
 
        // If weights of both 'u' and 'v'
        // are even then we make union of them.
        if(W[u] % 2 == 0 && W[v] % 2 == 0)
                    Union(u,v);
    }
}
 
// Function to find maximum
// size of DSU tree
int findMax(int n, int W[])
{
    int maxi = 0;
    for(int i = 1; i <= n; i++)
        if(W[i] % 2 == 0)
            maxi = max(maxi, sz[i]);  
             
    return maxi;
}
 
// Driver code
int main()
{
    /*
        Nodes are 0-indexed in this code
        So we have to make necessary changes
        while taking inputs
    */
 
    // Weights of nodes
    int W[] = {1, 2, 6, 4, 2, 0, 3};
 
    // Number of nodes in a tree
    int n = sizeof(W) / sizeof(W[0]);
 
    // Initializing every node as
    // a tree with single node.
    for(int i = 0; i < n; i++)
            id[i] = i, sz[i] = 1;
 
    Edge e[] = {{1, 2}, {1, 3}, {2, 4},
                {2, 5}, {4, 6}, {6, 7}};
 
    int q = sizeof(e) / sizeof(e[0]);
 
    UnionUtil(e, W, q);
 
    // Find maximum size of DSU tree.
    int maxi = findMax(n, W);
 
    printf("Maximum size of the subtree with ");
    printf("even weighted nodes = %d\n", maxi);
     
    return 0;
}


Java




// Java code to find maximum subtree such
// that all nodes are even in weight
class GFG
{
static int N = 100010;
 
// Structure for Edge
static class Edge
{
    int u, v;
 
    public Edge(int u, int v)
    {
        this.u = u;
        this.v = v;
    }
}
 
/*
'id': stores parent of a node.
'sz': stores size of a DSU tree.
*/
static int []id = new int[N];
static int []sz = new int[N];
 
// Function to assign root
static int Root(int idx)
{
    int i = idx;
     
    while(i != id[i])
    {
        id[i] = id[id[i]];
        i = id[i];
    }
    return i;
}
 
// Function to find Union
static void Union(int a, int b)
{
    int i = Root(a), j = Root(b);
     
    if (i != j)
    {
        if(sz[i] >= sz[j])
        {
            id[j] = i;
            sz[i] += sz[j];
            sz[j] = 0;
        }
        else
        {
            id[i] = j;
            sz[j] += sz[i];
            sz[i] = 0;
        }
    }
}
 
// Utility function for Union
static void UnionUtil(Edge e[], int W[], int q)
{
    for(int i = 0; i < q; i++)
    {
        // Edge between 'u' and 'v'
        int u, v;
        u = e[i].u;
        v = e[i].v;
 
        // 0-indexed nodes
        u--;
        v--;
 
        // If weights of both 'u' and 'v'
        // are even then we make union of them.
        if(W[u] % 2 == 0 && W[v] % 2 == 0)
            Union(u, v);
    }
}
 
// Function to find maximum
// size of DSU tree
static int findMax(int n, int W[])
{
    int maxi = 0;
    for(int i = 1; i < n; i++)
        if(W[i] % 2 == 0)
            maxi = Math.max(maxi, sz[i]);
             
    return maxi;
}
 
// Driver code
public static void main(String[] args)
{
    /*
    Nodes are 0-indexed in this code
    So we have to make necessary changes
    while taking inputs
    */
 
    // Weights of nodes
    int W[] = {1, 2, 6, 4, 2, 0, 3};
 
    // Number of nodes in a tree
    int n = W.length;
 
    // Initializing every node as
    // a tree with single node.
    for(int i = 0; i < n; i++)
    {
        id[i] = i;
        sz[i] = 1;
    }
 
    Edge e[] = {new Edge(1, 2), new Edge(1, 3),
                new Edge(2, 4), new Edge(2, 5),
                new Edge(4, 6), new Edge(6, 7)};
 
    int q = e.length;
 
    UnionUtil(e, W, q);
 
    // Find maximum size of DSU tree.
    int maxi = findMax(n, W);
 
    System.out.printf("Maximum size of the subtree with ");
    System.out.printf("even weighted nodes = %d\n", maxi);
}
}
 
// This code is contributed by Rajput-Ji


Python3




# Python3 code to find maximum subtree such
# that all nodes are even in weight
N = 100010
  
# Structure for Edge
class Edge:
     
    def __init__(self, u, v):
        self.u = u
        self.v = v
     
'''
    'id': stores parent of a node.
    'sz': stores size of a DSU tree.
'''
 
id = [0 for i in range(N)]
sz = [0 for i in range(N)];
  
# Function to assign root
def Root(idx):
 
    i = idx;
      
    while(i != id[i]):
         
        id[i] = id[id[i]]
        i = id[i];
      
    return i;
 
# Function to find Union
def Union(a, b):
 
    i = Root(a)
    j = Root(b);
      
    if (i != j):
     
        if(sz[i] >= sz[j]):
         
            id[j] = i
            sz[i] += sz[j];
            sz[j] = 0;
        else:
         
            id[i] = j
            sz[j] += sz[i];
            sz[i] = 0;
         
# Utility function for Union
def UnionUtil( e, W, q):
     
    for i in range(q):
      
         # Edge between 'u' and 'v'
        u = e[i].u
        v = e[i].v
  
        # 0-indexed nodes
        u -= 1
        v -= 1
  
        # If weights of both 'u' and 'v'
        # are even then we make union of them.
        if(W[u] % 2 == 0 and W[v] % 2 == 0):
            Union(u, v);
     
# Function to find maximum
# size of DSU tree
def findMax(n, W):
 
    maxi = 0
     
    for i in range(1, n):
     
        if(W[i] % 2 == 0):
            maxi = max(maxi, sz[i]);  
              
    return maxi;
 
# Driver code
if __name__=='__main__':
     
    '''
        Nodes are 0-indexed in this code
        So we have to make necessary changes
        while taking inputs
    '''
  
    # Weights of nodes
    W = [1, 2, 6, 4, 2, 0, 3]
  
    # Number of nodes in a tree
    n = len(W)
  
    # Initializing every node as
    # a tree with single node.
    for i in range(n):
     
            id[i] = i
            sz[i] = 1;
  
    e = [Edge(1, 2), Edge(1, 3), Edge(2, 4),
                Edge(2, 5), Edge(4, 6), Edge(6, 7)]
  
    q = len(e)
  
    UnionUtil(e, W, q);
  
    # Find maximum size of DSU tree.
    maxi = findMax(n, W);
  
    print("Maximum size of the subtree with ", end='');
    print("even weighted nodes =", maxi);
      
# This code is contributed by rutvik_56


C#




// C# code to find maximum subtree such
// that all nodes are even in weight
using System;
 
class GFG
{
static int N = 100010;
 
// Structure for Edge
public class Edge
{
    public int u, v;
 
    public Edge(int u, int v)
    {
        this.u = u;
        this.v = v;
    }
}
 
/*
'id': stores parent of a node.
'sz': stores size of a DSU tree.
*/
static int []id = new int[N];
static int []sz = new int[N];
 
// Function to assign root
static int Root(int idx)
{
    int i = idx;
     
    while(i != id[i])
    {
        id[i] = id[id[i]];
        i = id[i];
    }
    return i;
}
 
// Function to find Union
static void Union(int a, int b)
{
    int i = Root(a), j = Root(b);
     
    if (i != j)
    {
        if(sz[i] >= sz[j])
        {
            id[j] = i;
            sz[i] += sz[j];
            sz[j] = 0;
        }
        else
        {
            id[i] = j;
            sz[j] += sz[i];
            sz[i] = 0;
        }
    }
}
 
// Utility function for Union
static void UnionUtil(Edge []e, int []W, int q)
{
    for(int i = 0; i < q; i++)
    {
        // Edge between 'u' and 'v'
        int u, v;
        u = e[i].u;
        v = e[i].v;
 
        // 0-indexed nodes
        u--;
        v--;
 
        // If weights of both 'u' and 'v'
        // are even then we make union of them.
        if(W[u] % 2 == 0 && W[v] % 2 == 0)
            Union(u, v);
    }
}
 
// Function to find maximum
// size of DSU tree
static int findMax(int n, int []W)
{
    int maxi = 0;
    for(int i = 1; i < n; i++)
        if(W[i] % 2 == 0)
            maxi = Math.Max(maxi, sz[i]);
             
    return maxi;
}
 
// Driver code
public static void Main(String[] args)
{
    /*
    Nodes are 0-indexed in this code
    So we have to make necessary changes
    while taking inputs
    */
 
    // Weights of nodes
    int []W = {1, 2, 6, 4, 2, 0, 3};
 
    // Number of nodes in a tree
    int n = W.Length;
 
    // Initializing every node as
    // a tree with single node.
    for(int i = 0; i < n; i++)
    {
        id[i] = i;
        sz[i] = 1;
    }
 
    Edge []e = {new Edge(1, 2), new Edge(1, 3),
                new Edge(2, 4), new Edge(2, 5),
                new Edge(4, 6), new Edge(6, 7)};
 
    int q = e.Length;
 
    UnionUtil(e, W, q);
 
    // Find maximum size of DSU tree.
    int maxi = findMax(n, W);
 
    Console.Write("Maximum size of the subtree with ");
    Console.WriteLine("even weighted nodes = {0}\n", maxi);
}
}
 
// This code is contributed by Princi Singh


Javascript




<script>
 
// Javascript code to find maximum subtree such
// that all nodes are even in weight
let N = 100010;
 
/*
'id': stores parent of a node.
'sz': stores size of a DSU tree.
*/
let id = new Array(N);
let sz = new Array(N);
 
// Function to assign root
function Root(idx)
{
    let i = idx;
 
    while(i != id[i])
    {
        id[i] = id[id[i]];
        i = id[i];
    }
    return i;
}
 
// Function to find Union
function Union(a, b)
{
    let i = Root(a), j = Root(b);
 
    if (i != j)
    {
        if (sz[i] >= sz[j])
        {
            id[j] = i;
            sz[i] += sz[j];
            sz[j] = 0;
        }
        else
        {
            id[i] = j;
            sz[j] += sz[i];
            sz[i] = 0;
        }
    }
}
 
// Utility function for Union
function UnionUtil(e, W, q)
{
    for(let i = 0; i < q; i++)
    {
         
        // Edge between 'u' and 'v'
        let u, v;
        u = e[i][0];
        v = e[i][1];
 
        // 0-indexed nodes
        u--;
        v--;
 
        // If weights of both 'u' and 'v'
        // are even then we make union of them.
        if (W[u] % 2 == 0 && W[v] % 2 == 0)
            Union(u, v);
    }
}
 
// Function to find maximum
// size of DSU tree
function findMax(n, W)
{
    let maxi = 0;
    for(let i = 1; i < n; i++)
        if (W[i] % 2 == 0)
            maxi = Math.max(maxi, sz[i]);
 
    return maxi;
}
 
// Driver code
 
/*
Nodes are 0-indexed in this code
So we have to make necessary changes
while taking inputs
*/
 
// Weights of nodes
let W = [ 1, 2, 6, 4, 2, 0, 3 ];
 
// Number of nodes in a tree
let n = W.length;
 
// Initializing every node as
// a tree with single node.
for(let i = 0; i < n; i++)
{
    id[i] = i;
    sz[i] = 1;
}
 
let e = [ [ 1, 2 ], [ 1, 3 ],
          [ 2, 4 ], [ 2, 5 ],
          [ 4, 6 ], [ 6, 7 ] ];
let q = e.length;
 
UnionUtil(e, W, q);
 
// Find maximum size of DSU tree.
let maxi = findMax(n, W);
 
document.write("Maximum size of the subtree with ");
document.write("even weighted nodes = " + maxi);
 
// This code is contributed by divyesh072019
 
</script>


Output

Maximum size of the subtree with even weighted nodes = 4

Time complexity : O(q log n) where q is the number of edges and n is the number of nodes.

Space Complexity : O(n)



Previous Article
Next Article

Similar Reads

Disjoint Set Union on trees | Set 2
Given a tree, and the cost of a subtree is defined as |S|*AND(S) where |S| is the size of the subtree and AND(S) is bitwise AND of all indices of nodes from the subtree, task is to find maximum cost of possible subtree. Prerequisite : Disjoint Set Union Examples: Input : Number of nodes = 4 Edges = (1, 2), (3, 4), (1, 3) Output : Maximum cost = 4 E
14 min read
Extended Disjoint Set Union on Trees
Prerequisites: DFS, Trees, DSUGiven a tree with of N nodes from value 1 to N and E edges and array arr[] which denotes number associated to each node. You are also given Q queries which contains 2 integers {V, F}. For each query, there is a subtree with vertex V, the task is to check if there exists count of numbers associated with each node in tha
15 min read
Test case generator for Tree using Disjoint-Set Union
In this article, we will generate test cases such that given set edges form a Tree. Below are the two conditions of the Tree: It should have one less edge than the number of vertices.There should be no cycle in it. Approach: The idea is to run a loop and add one edge each time that is generated randomly, and for adding each edge we will check wheth
11 min read
Disjoint Set Union (Randomized Algorithm)
A Disjoint set union is an algorithm that is used to manage a collection of disjoint sets. A disjoint set is a set in which the elements are not in any other set. Also, known as union-find or merge-find. The disjoint set union algorithm allows you to perform the following operations efficiently: Find: Determine which set a given element belongs to.
15+ min read
Number of connected components of a graph ( using Disjoint Set Union )
Given an undirected graph G with vertices numbered in the range [0, N] and an array Edges[][] consisting of M edges, the task is to find the total number of connected components in the graph using Disjoint Set Union algorithm. Examples: Input: N = 4, Edges[][] = {{1, 0}, {2, 3}, {3, 4}}Output: 2Explanation: There are only 2 connected components as
7 min read
Introduction to Disjoint Set (Union-Find Algorithm)
What is a Disjoint set data structure?Two sets are called disjoint sets if they don't have any element in common, the intersection of sets is a null set. A data structure that stores non overlapping or disjoint subset of elements is called disjoint set data structure. The disjoint set data structure supports following operations: Adding new sets to
15+ min read
Calculate number of nodes between two vertices in an acyclic Graph by Disjoint Union method
Given a connected acyclic graph, a source vertex and a destination vertex, your task is to count the number of vertices between the given source and destination vertex by Disjoint Union Method . Examples: Input : 1 4 4 5 4 2 2 6 6 3 1 3 Output : 3 In the input 6 is the total number of vertices labeled from 1 to 6 and the next 5 lines are the connec
10 min read
Union By Rank and Path Compression in Union-Find Algorithm
In the previous post, we introduced union find algorithm and used it to detect cycles in a graph. We used the following union() and find() operations for subsets. C/C++ Code // Naive implementation of find int find(int parent[], int i) { if (parent[i] == -1) return i; return find(parent, parent[i]); } // Naive implementation of union() void Union(i
15+ min read
Union-Find Algorithm | (Union By Rank and Find by Optimized Path Compression)
Check whether a given graph contains a cycle or not. Example: Input: Output: Graph contains Cycle. Input: Output: Graph does not contain Cycle. Prerequisites: Disjoint Set (Or Union-Find), Union By Rank and Path CompressionWe have already discussed union-find to detect cycle. Here we discuss find by path compression, where it is slightly modified t
13 min read
Introduction to Generic Trees (N-ary Trees)
Generic trees are a collection of nodes where each node is a data structure that consists of records and a list of references to its children(duplicate references are not allowed). Unlike the linked list, each node stores the address of multiple nodes. Every node stores address of its children and the very first node's address will be stored in a s
5 min read