Skip to main content

Number of Ways to Assign Edge Weights II - Solution & Explanation

HardArrayMathDynamic ProgrammingBit Manipulation5 min readAsked at: Amazon, Google, Bloomberg
Practice this problem

Problem Statement

There is an undirected tree with n nodes labeled from 1 to n, rooted at node 1. The tree is represented by a 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi.

Initially, all edges have a weight of 0. You must assign each edge a weight of either 1 or 2.

The cost of a path between any two nodes u and v is the total weight of all edges in the path connecting them.

You are given a 2D integer array queries. For each queries[i] = [ui, vi], determine the number of ways to assign weights to edges in the path such that the cost of the path between ui and vi is odd.

Return an array answer, where answer[i] is the number of valid assignments for queries[i].

Since the answer may be large, apply modulo 109 + 7 to each answer[i].

Note: For each query, disregard all edges not in the path between node ui and vi.

 

Example 1:

Input: edges = [[1,2]], queries = [[1,1],[1,2]]

Output: [0,1]

Explanation:

  • Query [1,1]: The path from Node 1 to itself consists of no edges, so the cost is 0. Thus, the number of valid assignments is 0.
  • Query [1,2]: The path from Node 1 to Node 2 consists of one edge (1 → 2). Assigning weight 1 makes the cost odd, while 2 makes it even. Thus, the number of valid assignments is 1.

Example 2:

Input: edges = [[1,2],[1,3],[3,4],[3,5]], queries = [[1,4],[3,4],[2,5]]

Output: [2,1,4]

Explanation:

  • Query [1,4]: The path from Node 1 to Node 4 consists of two edges (1 → 3 and 3 → 4). Assigning weights (1,2) or (2,1) results in an odd cost. Thus, the number of valid assignments is 2.
  • Query [3,4]: The path from Node 3 to Node 4 consists of one edge (3 → 4). Assigning weight 1 makes the cost odd, while 2 makes it even. Thus, the number of valid assignments is 1.
  • Query [2,5]: The path from Node 2 to Node 5 consists of three edges (2 → 1, 1 → 3, and 3 → 5). Assigning (1,2,2), (2,1,2), (2,2,1), or (1,1,1) makes the cost odd. Thus, the number of valid assignments is 4.

 

Constraints:

  • 2 <= n <= 105
  • edges.length == n - 1
  • edges[i] == [ui, vi]
  • 1 <= queries.length <= 105
  • queries[i] == [ui, vi]
  • 1 <= ui, vi <= n
  • edges represents a valid tree.

Approach Overview

Problem Overview: You are given a tree and must assign weights to its edges while satisfying specific constraints defined by the problem. The task is to count how many valid assignments exist. Because the structure is a tree, the solution relies heavily on depth-first traversal and dynamic programming to combine valid configurations from child subtrees.

Approach 1: Brute Force Edge Assignment (Exponential Time)

The most direct idea is to try every possible weight assignment for every edge and check whether the resulting configuration satisfies the constraints. With n-1 edges, even a small number of possible weights leads to exponential combinations. After assigning weights, you validate the tree by traversing it and verifying the conditions. This approach has O(k^(n)) time complexity where k is the number of possible weights, and O(n) space for traversal state. It works only for very small inputs and mainly serves as a conceptual baseline.

Approach 2: Tree Dynamic Programming with DFS (Optimal)

The efficient strategy uses Depth-First Search to process the tree from the root while maintaining dynamic programming states for each subtree. For every node, you compute how many valid assignments exist for the subtree depending on the state propagated from its parent edge. Each child contributes a set of valid configurations, and the parent combines them using multiplication or state transitions.

Bit manipulation helps encode constraint states efficiently. For example, if the validity of assignments depends on parity or bitwise conditions along a path, you represent those properties using a bitmask and update them while traversing edges. This keeps transitions constant time and avoids recomputation. The DFS aggregates results from children and stores them in a DP table per node.

This approach runs in O(n * s) time where s is the number of possible DP states derived from the bitmask or constraint representation. Space complexity is O(n * s) for storing DP states across the tree. The method combines ideas from Dynamic Programming, Tree algorithms, and bitmask state compression.

Recommended for interviews: Interviewers expect the tree DP approach with DFS. Starting with the brute force explanation shows you understand the search space, but recognizing that the tree structure allows state aggregation from children demonstrates strong algorithmic reasoning.

Solution

Code

C

Try this approach in the editor →

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Brute Force Edge AssignmentO(k^n)O(n)Useful only for very small trees or reasoning about the search space
Tree DP with DFS and Bitmask StatesO(n * s)O(n * s)General case; scalable for large trees with constrained state transitions

Video Solution

Number of Ways to Assign Edge Weights II | Leetcode 3559 | Binary Lifting | Concepts & Questions - 4 • codestorywithMIK • 6,864 views views

Watch 9 more video solutions →

Frequently Asked Questions

Is Number of Ways to Assign Edge Weights II easy or hard?
Number of Ways to Assign Edge Weights II is classified as Hard. The challenge comes from combining tree traversal with dynamic programming and efficiently representing constraint states using bit manipulation or compressed DP states.
Number of Ways to Assign Edge Weights II Python/Java solution
Implement the algorithm by building an adjacency list for the tree and running a DFS from the root. During traversal, maintain DP arrays or maps that store the number of valid configurations for each state. The same logic translates cleanly across Python, Java, C++, and Go.
How to solve Number of Ways to Assign Edge Weights II in O(n)?
A near-linear solution is achieved by performing a single DFS traversal of the tree and computing DP states at each node. Instead of enumerating all assignments, the algorithm aggregates counts from child subtrees and updates states using constant-time transitions. This keeps the traversal close to O(n) when the number of states is small.
What is the best approach for Number of Ways to Assign Edge Weights II?
The most efficient method uses tree dynamic programming combined with depth-first search. Each node computes the number of valid configurations for its subtree based on the state passed from its parent edge. Bitmasking or compact state encoding keeps transitions fast, leading to an overall complexity of O(n * states).
Is Number of Ways to Assign Edge Weights II asked at Google/Amazon/Meta?
Problems involving tree DP, edge assignments, and state propagation appear frequently in interviews at companies like Google, Amazon, and Meta. Variants of this problem test understanding of DFS traversal, subtree aggregation, and dynamic programming on trees.
What data structure is used in Number of Ways to Assign Edge Weights II?
The core structure is a tree represented with an adjacency list. The solution relies on depth-first search to traverse nodes and dynamic programming tables to store valid assignment counts for each state. Bit manipulation is often used to encode constraints efficiently.
What is the time complexity of Number of Ways to Assign Edge Weights II?
The optimal tree DP solution runs in O(n * s) time, where n is the number of nodes and s is the number of possible constraint states represented in the DP. Space complexity is also O(n * s) because each node stores results for its DP states.

Ready to solve this problem?

Practice Number of Ways to Assign Edge Weights II with our built-in code editor and test cases.

Practice on FleetCode