Problem
There is an undirected tree with n nodes labeled from 0 to n - 1. You are given the integer n and a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the tree.
You are also given a 0-indexed integer array values of length n, where values[i] is the value associated with the ith node, and an integer k.
A valid split of the tree is obtained by removing any set of edges, possibly empty, from the tree such that the resulting components all have values that are divisible by k, where the value of a connected component is the sum of the values of its nodes.
Return themaximum number of components in any valid split.
Examples
Example 1:
graph LR
subgraph Original
A1[1]
B1[2]
C1[3]
D1[4]
E1[0]
A1 --> B1 & C1
B1 --> D1 & E1
end
subgraph After["After Split"]
A2[1]
B2[2]
C2[3]
D2[4]
E2[0]
A2 ~~~ B2
A2 --> C2
B2 --> D2 & E2
end
Original --> After
style A1 stroke:#f66,stroke-width:2px
style B1 stroke:#f66,stroke-width:2px
| |
Example 2:
graph LR
subgraph Original
A1[1]
B1[2]
C1[3]
D1[4]
E1[5]
F1[6]
G1[0]
G1 --> B1 & A1
B1 --> F1 & E1
A1 --> D1 & C1
end
subgraph After["After Split"]
A2[1]
B2[2]
C2[3]
D2[4]
E2[5]
F2[6]
G2[0]
G2 ~~~ B2 & A2
B2 --> F2 & E2
A2 --> D2 & C2
end
Original --> After
style A1 stroke:#f66,stroke-width:2px
style B1 stroke:#f66,stroke-width:2px
| |
Constraints:
1 <= n <= 3 * 10^4edges.length == n - 1edges[i].length == 20 <= ai, bi < nvalues.length == n0 <= values[i] <= 10^91 <= k <= 10^9- Sum of
valuesis divisible byk. - The input is generated such that
edgesrepresents a valid tree.
Solution
Method 1 - Using DFS
To solve this problem, let’s leverage the structure of a tree. A tree is composed of nodes and edges, where each edge connects a parent node to a child node. When we choose a node as the root, we can decompose the tree into subtrees based on these parent-child relationships. Since the tree is undirected, any node can be selected as the root without affecting the result.
Using recursion, we can calculate the sum of values for each subtree. Once we have the sum, we need to check if it is divisible by k. If it is, we can detach the subtree at that point, treating it as a valid component.
If the sum is not divisible by k, the remainder (i.e., the non-divisible part when divided by k) must be carried over to the parent node. The parent node will then combine its remainder with those of its children to determine if the total sum is divisible by k. This approach is well-suited to Depth-First Search (DFS) recursion:
- Start from the leaves (smallest subtrees) and calculate their sums.
- Propagate the results upwards to parent nodes, aggregating remainders modulo
k. - Count a subtree as a valid component whenever its sum is divisible by
k.
Here is the approach:
- Initialize an adjacency list
adjListto represent the graph. - Populate
adjListusing the given edges. - Initialize
componentCountto 0 to store the count of k-divisible components. - Call
dfs(0, -1, adjList, values, k, componentCount)starting from node 0 with no parent (-1). - Return
componentCountas the result.
This is how the dfs will work:
- Initialize
sumto 0, representing the sum of node values in the current subtree. - For each
neighborNodeofcurrentNode:- If
neighborNodeis not equal toparentNode, recursively calldfsforneighborNodewithcurrentNodeas its parent. - Add the result of the recursive call to
sumand take modulok.
- If
- Add the value of
currentNodetosumand take modulok. - If
sumis 0, incrementcomponentCountbecause the current subtree forms a k-divisible component. - Return
sumto allow the parent node to incorporate the result.
Code
| |
| |
Complexity
- ⏰ Time complexity:
O(n), wherenis the number of nodes. Each node and edge is visited once during DFS traversal. - 🧺 Space complexity:
O(n)for storing the adjacency list and the DFS recursion stack.