Similar Problems

Similar Problems not available

Count Number Of Possible Root Nodes - Leetcode Solution

Companies:

LeetCode:  Count Number Of Possible Root Nodes Leetcode Solution

Difficulty: Hard

Topics: hash-table dynamic-programming tree depth-first-search  

Problem:

Given a tree with n nodes. Consider that each node of the tree is labeled from 1 to n. We define a root of the tree to be any node on the tree, such that the entire tree can be reached from it (i.e. there exists a path from the root node to every other node in the tree).

You are given a list of edges where each pair of edges represents an undirected edge connecting two nodes in the tree. You need to count the number of different possible roots of the tree.

Solution:

To solve this problem, we need to understand the concept of centroid of a tree. A centroid is a node in the tree such that if we remove it, then the maximum size of any connected component should be as small as possible. We can find the centroid of a tree using the Centroid Decomposition algorithm.

Algorithm of Centroid Decomposition:

  1. Select an arbitrary node x to be the root of the tree.
  2. Compute the size of every subtree rooted at every node in the tree. Denote this as subsize[u] for the node u.
  3. Find the node c such that for every child v of c, subsize[v] ≤ n/2 and subsize[c] > n/2. This node c is called the centroid of the tree.
  4. Recursively apply the algorithm to each connected component of the tree obtained by removing the centroid.

Using the Centroid Decomposition algorithm, we can find the centroids of the tree. We can then count the number of possible roots as follows:

  1. If the tree has only one node, then the number of possible roots is 1.
  2. If the tree has more than one node, then for each centroid c, we can make c as the root and count the number of nodes in the subtree below c. Denote this as subtree_size[c].
  3. Let total_size be the total number of nodes in the tree. Then the number of nodes above the centroid c is total_size - subtree_size[c].
  4. If total_size - subtree_size[c] ≤ n/2, then we can make c as the root.
  5. For every child v of c, we can check if subtree_size[v] > n/2. If subtree_size[v] > n/2, then we cannot make v as the root because the maximum size of any connected component should be as small as possible.
  6. Recursively apply the algorithm to each connected component of the tree obtained by removing the centroid.

The time complexity of this algorithm is O(n log n), where n is the number of nodes in the tree. This is because we need to compute the size of every subtree and find the centroid of the tree, which takes O(n log n) time using DFS and binary search. We then need to process each centroid and its children, which also takes O(n log n) time.

The Python implementation of the above algorithm is given below:

class Solution(object):
    def countSubtreesWithAllOnes(self, n, edges):
        """
        :type n: int
        :type edges: List[List[int]]
        :rtype: List[int]
        """
        def dfs(u, p):
            subsize[u] = 1
            centroid_size = 0
            for v in adj[u]:
                if v != p:
                    dfs(v, u)
                    subsize[u] += subsize[v]
                    centroid_size = max(centroid_size, subsize[v])
            centroid_size = max(centroid_size, total_size - subsize[u])
            if centroid_size <= n // 2:
                centroids.append(u)
        
        def count(u, p):
            res = 1
            for v in adj[u]:
                if v != p and subtree_size[v] <= n // 2:
                    res += count(v, u)
            return res
        
        adj = [[] for _ in range(n)]
        for u, v in edges:
            adj[u-1].append(v-1)
            adj[v-1].append(u-1)
        centroids = []
        subsize = [0] * n
        dfs(0, -1)
        total_size = subsize[0]
        for c in centroids:
            subtree_size = [0] * n
            for v in adj[c]:
                if subsize[v] > subsize[c]:
                    subtree_size[v] = total_size - subsize[c]
                else:
                    subtree_size[v] = subsize[v]
            subtree_size[c] = subsize[c]
            count_one = count(c, -1)
            res = 0
            for v in adj[c]:
                if subsize[v] > subsize[c] and subtree_size[v] > n // 2:
                    res = 0
                    break
                if subtree_size[v] <= n // 2:
                    res += count(v, c)
            if res > 0:
                count_one += res + 1
            ans[c] = count_one
        return ans

In this implementation, we first build the adjacency list of the tree from the given edges. We then find the centroids of the tree using the dfs function. For each centroid, we compute the size of all subtrees below it. We then count the number of possible roots for each centroid using the count function. Finally, we return the list of counts for all centroids as the answer.

Count Number Of Possible Root Nodes Solution Code

1