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] = [u_i, v_i] indicates that there is an edge between nodes u_i and v_i.
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] = [u_i, v_i], determine the number of ways to assign weights to edges in the path such that the cost of the path between u_i and v_i 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 10^9 + 7 to each answer[i].
Note: For each query, disregard all edges not in the path between node u_i and v_i.
💡 Note:For query [1,4]: path 1→2→3→4 has 3 edges, so 2^(3-1) = 4 ways to make sum odd. For query [2,3]: path 2→3 has 1 edge, so 2^(1-1) = 1 way to make sum odd.
💡 Note:Query [1,2]: 1 edge, 1 way to make odd (weight=1). Query [2,3]: 1 edge, 1 way to make odd. Query [1,3]: path 1→2→3 has 2 edges, 2^(2-1) = 2 ways to make sum odd.
Example 3 — Same Node Query
$Input:edges = [[1,2]], queries = [[1,1],[2,2]]
›Output:[0,0]
💡 Note:Same node queries have 0 edges in path, cannot make sum odd (sum is 0), so 0 ways.
Number of Ways to Assign Edge Weights II — Solution
The key insight is that for a path with k edges, there are exactly 2^(k-1) ways to assign weights (1 or 2) such that the total sum is odd. This is because we need an odd number of edges with weight 1. Best approach uses tree preprocessing with parent pointers for efficient path length queries. Time: O(N + Q), Space: O(N)
Common Approaches
✓
Brute Force Path Finding
⏱️ Time: O(Q × N)
Space: O(N)
For each query, use DFS to find the unique path between two nodes in the tree. Then calculate how many ways to assign weights 1 or 2 to make the sum odd.
Optimized with LCA Preprocessing
⏱️ Time: O(N + Q × log N)
Space: O(N)
Build the tree structure once with parent pointers and node depths. For each query, find the path length using lowest common ancestor (LCA) approach without full DFS traversal.
Brute Force Path Finding — Algorithm Steps
Step 1: Build adjacency list from edges
Step 2: For each query, use DFS to find path between u and v
Step 3: Count edges in path, calculate 2^(edges-1) mod (10^9+7)
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Build Graph
Create adjacency list from edges
2
Find Path
Use DFS to find unique path between query nodes
3
Calculate Ways
Count edges in path, compute 2^(k-1) for odd sums
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MOD 1000000007
#define MAX_N 10005
static int adj[MAX_N][100];
static int adjCount[MAX_N];
static int visited[MAX_N];
static int path[MAX_N];
static int pathSize;
long long powerMod(long long base, long long exp, long long mod) {
long long result = 1;
base = base % mod;
while (exp > 0) {
if (exp % 2 == 1) {
result = (result * base) % mod;
}
exp = exp >> 1;
base = (base * base) % mod;
}
return result;
}
int findPath(int start, int end) {
if (start == end) {
return 1;
}
visited[start] = 1;
for (int i = 0; i < adjCount[start]; i++) {
int neighbor = adj[start][i];
if (!visited[neighbor]) {
path[pathSize++] = neighbor;
if (findPath(neighbor, end)) {
return 1;
}
pathSize--;
}
}
return 0;
}
int* solution(int** edges, int edgesSize, int** queries, int queriesSize, int* returnSize) {
*returnSize = queriesSize;
int* result = (int*)malloc(queriesSize * sizeof(int));
int n = edgesSize + 1;
// Build adjacency list
memset(adjCount, 0, sizeof(adjCount));
for (int i = 0; i < edgesSize; i++) {
int u = edges[i][0];
int v = edges[i][1];
adj[u][adjCount[u]++] = v;
adj[v][adjCount[v]++] = u;
}
for (int q = 0; q < queriesSize; q++) {
int u = queries[q][0];
int v = queries[q][1];
if (u == v) {
result[q] = 0;
continue;
}
memset(visited, 0, sizeof(visited));
pathSize = 1;
path[0] = u;
findPath(u, v);
int edgeCount = pathSize - 1;
if (edgeCount == 0) {
result[q] = 0;
} else {
// For k edges, 2^(k-1) ways to make sum odd
long long ways = powerMod(2, edgeCount - 1, MOD);
result[q] = (int)ways;
}
}
return result;
}
void skipWhitespace(char** ptr) {
while (**ptr && isspace(**ptr)) (*ptr)++;
}
int parseInt(char** ptr) {
skipWhitespace(ptr);
int sign = 1;
if (**ptr == '-') {
sign = -1;
(*ptr)++;
}
int num = 0;
while (**ptr && isdigit(**ptr)) {
num = num * 10 + (**ptr - '0');
(*ptr)++;
}
return num * sign;
}
int** parse2DArray(char* str, int* rows, int* cols) {
int capacity = 100;
int** arr = (int**)malloc(capacity * sizeof(int*));
*rows = 0;
*cols = 2;
char* ptr = str;
skipWhitespace(&ptr);
if (*ptr == '[') ptr++;
while (*ptr != '\0' && *ptr != ']') {
skipWhitespace(&ptr);
if (*ptr == '[') {
ptr++;
if (*rows >= capacity) {
capacity *= 2;
arr = (int**)realloc(arr, capacity * sizeof(int*));
}
arr[*rows] = (int*)malloc(2 * sizeof(int));
arr[*rows][0] = parseInt(&ptr);
skipWhitespace(&ptr);
if (*ptr == ',') ptr++;
arr[*rows][1] = parseInt(&ptr);
(*rows)++;
skipWhitespace(&ptr);
if (*ptr == ']') ptr++;
}
skipWhitespace(&ptr);
if (*ptr == ',') ptr++;
}
return arr;
}
int main() {
char line[100000];
if (fgets(line, sizeof(line), stdin) == NULL) return 0;
int edgesRows, edgesCols;
int** edges = parse2DArray(line, &edgesRows, &edgesCols);
if (fgets(line, sizeof(line), stdin) == NULL) {
for (int i = 0; i < edgesRows; i++) free(edges[i]);
free(edges);
return 0;
}
int queriesRows, queriesCols;
int** queries = parse2DArray(line, &queriesRows, &queriesCols);
int returnSize;
int* result = solution(edges, edgesRows, queries, queriesRows, &returnSize);
printf("[");
for (int i = 0; i < returnSize; i++) {
printf("%d", result[i]);
if (i < returnSize - 1) printf(",");
}
printf("]\n");
for (int i = 0; i < edgesRows; i++) free(edges[i]);
free(edges);
for (int i = 0; i < queriesRows; i++) free(queries[i]);
free(queries);
free(result);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(Q × N)
For Q queries, each DFS traversal can visit up to N nodes
n
2n
✓ Linear Growth
Space Complexity
O(N)
Adjacency list stores N nodes and N-1 edges, plus DFS recursion stack
n
2n
✓ Linear Space
12.5K Views
MediumFrequency
~35 minAvg. Time
387 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.