You are given an undirected tree rooted at node 0, with n nodes numbered from 0 to n-1. The tree is represented by a 2D integer array edges where edges[i] = [ui, vi] indicates an edge between nodes ui and vi.
You are also given:
An integer array nums of length n, where nums[i] represents the value at node i
An integer k representing the minimum distance constraint
Subtree Inversion Operation: When you invert a node, every value in the subtree rooted at that node is multiplied by -1.
Distance Constraint: You may only invert a node if it is "sufficiently far" from any other inverted node. Specifically, if you invert two nodes a and b such that one is an ancestor of the other, then the distance between them must be at least k.
Your goal is to maximize the sum of all node values in the tree after applying optimal inversion operations.
Input & Output
example_1.py โ Basic Tree
$Input:edges = [[0,1],[0,2]], nums = [1,-3,4], k = 2
โบOutput:8
๐ก Note:We can invert node 1 (which only affects itself since it's a leaf). This changes nums[1] from -3 to 3. The final sum is 1 + 3 + 4 = 8.
example_2.py โ Distance Constraint
$Input:edges = [[0,1],[1,2],[1,3]], nums = [1,-2,-3,4], k = 2
โบOutput:10
๐ก Note:We can invert nodes 0 and 2 since the distance between them is 2 (exactly k). Inverting 0 changes the entire tree to [-1,2,3,-4], then inverting 2 changes it to [-1,2,-3,-4]. Sum = -1 + 2 + (-3) + (-4) = -6. Better: invert only node 1, giving [1,2,3,-4] with sum = 2.
example_3.py โ Single Node
$Input:edges = [], nums = [-5], k = 1
โบOutput:5
๐ก Note:With only one node, we can invert it to change -5 to 5, giving us the maximum possible sum of 5.
Constraints
1 โค n โค 20
edges.length = n - 1
0 โค edges[i][0], edges[i][1] < n
The input represents a valid tree
-104 โค nums[i] โค 104
1 โค k โค n
The tree is connected and acyclic
Visualization
Tap to expand
Understanding the Visualization
1
Build Tree Structure
Convert the edge list into a rooted tree with parent-child relationships
2
Calculate Distances
For any two nodes, find their distance using LCA (Lowest Common Ancestor)
3
Try All Valid Combinations
Generate all possible inversion sets that satisfy the distance constraint
4
Apply Inversions and Sum
For each valid combination, invert the subtrees and calculate the total sum
5
Return Maximum
Track and return the maximum sum achieved across all valid combinations
Key Takeaway
๐ฏ Key Insight: At each node, we face a choice - invert the current subtree (affecting all descendants) or allow deeper nodes to make independent inversion decisions. The distance constraint k prevents us from having inversions too close together in the ancestor-descendant chain.
This problem requires dynamic programming on trees with constraint checking. The optimal approach uses DFS with memoization to decide at each node whether to invert the current subtree or allow deeper inversions, while respecting the distance constraint k. The brute force solution tries all 2^n combinations, but the optimal DP solution runs in O(nยฒ) time by making optimal decisions locally.
Common Approaches
Approach
Time
Space
Notes
โ
Brute Force (Try All Combinations)
O(2^n * n^2)
O(n)
Try all possible combinations of node inversions and check constraints
Brute Force (Try All Combinations) โ Algorithm Steps
Generate all possible subsets of nodes (2^n combinations)
For each subset, check if distance constraints are satisfied
Calculate the resulting sum after inversions
Return the maximum sum found
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Generate Combinations
Create all possible subsets of nodes to invert using bitmask
2
Check Distance Constraints
For each combination, verify that inverted ancestor-descendant pairs are at least k distance apart
3
Calculate Sum
Apply inversions to each valid combination and calculate the resulting sum
4
Find Maximum
Track and return the maximum sum found across all valid combinations
Code -
solution.c โ C
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_N 20
typedef struct {
int graph[MAX_N][MAX_N];
int graphSize[MAX_N];
int parent[MAX_N];
int children[MAX_N][MAX_N];
int childrenSize[MAX_N];
int n, k;
} Solution;
void dfsBuild(Solution* s, int node, int par) {
s->parent[node] = par;
for (int i = 0; i < s->graphSize[node]; i++) {
int neighbor = s->graph[node][i];
if (neighbor != par) {
s->children[node][s->childrenSize[node]++] = neighbor;
dfsBuild(s, neighbor, node);
}
}
}
int isAncestor(Solution* s, int a, int b) {
int curr = b;
while (curr != -1) {
if (curr == a) return 1;
curr = s->parent[curr];
}
return 0;
}
int getDistance(Solution* s, int a, int b) {
int pathA[MAX_N], pathB[MAX_N];
int pathASize = 0, pathBSize = 0;
int tempA = a, tempB = b;
while (tempA != -1) {
pathA[pathASize++] = tempA;
tempA = s->parent[tempA];
}
while (tempB != -1) {
pathB[pathBSize++] = tempB;
tempB = s->parent[tempB];
}
// Reverse paths
for (int i = 0; i < pathASize / 2; i++) {
int temp = pathA[i];
pathA[i] = pathA[pathASize - 1 - i];
pathA[pathASize - 1 - i] = temp;
}
for (int i = 0; i < pathBSize / 2; i++) {
int temp = pathB[i];
pathB[i] = pathB[pathBSize - 1 - i];
pathB[pathBSize - 1 - i] = temp;
}
int lcaIdx = 0;
while (lcaIdx < pathASize && lcaIdx < pathBSize && pathA[lcaIdx] == pathB[lcaIdx]) {
lcaIdx++;
}
return pathASize + pathBSize - 2 * lcaIdx;
}
int checkConstraints(Solution* s, int* invertedNodes, int size) {
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
int a = invertedNodes[i], b = invertedNodes[j];
if (isAncestor(s, a, b) || isAncestor(s, b, a)) {
if (getDistance(s, a, b) < s->k) {
return 0;
}
}
}
}
return 1;
}
void invertSubtree(Solution* s, int* resultNums, int node) {
resultNums[node] *= -1;
for (int i = 0; i < s->childrenSize[node]; i++) {
invertSubtree(s, resultNums, s->children[node][i]);
}
}
long long calculateSum(Solution* s, int* nums, int* invertedNodes, int size) {
int resultNums[MAX_N];
for (int i = 0; i < s->n; i++) {
resultNums[i] = nums[i];
}
for (int i = 0; i < size; i++) {
invertSubtree(s, resultNums, invertedNodes[i]);
}
long long sum = 0;
for (int i = 0; i < s->n; i++) {
sum += resultNums[i];
}
return sum;
}
long long maxSubtreeSum(int edges[][2], int edgesSize, int* nums, int numsSize, int k) {
Solution s;
s.n = numsSize;
s.k = k;
if (s.n == 1) {
return abs(nums[0]);
}
// Initialize
for (int i = 0; i < s.n; i++) {
s.graphSize[i] = 0;
s.childrenSize[i] = 0;
}
// Build graph
for (int i = 0; i < edgesSize; i++) {
int u = edges[i][0], v = edges[i][1];
s.graph[u][s.graphSize[u]++] = v;
s.graph[v][s.graphSize[v]++] = u;
}
dfsBuild(&s, 0, -1);
long long maxSum = 0;
for (int i = 0; i < s.n; i++) {
maxSum += nums[i];
}
// Try all combinations
for (int mask = 1; mask < (1 << s.n); mask++) {
int invertedNodes[MAX_N];
int size = 0;
for (int i = 0; i < s.n; i++) {
if (mask & (1 << i)) {
invertedNodes[size++] = i;
}
}
if (checkConstraints(&s, invertedNodes, size)) {
long long currentSum = calculateSum(&s, nums, invertedNodes, size);
if (currentSum > maxSum) {
maxSum = currentSum;
}
}
}
return maxSum;
}
int main() {
// Parse input and call solution
return 0;
}
Time & Space Complexity
Time Complexity
โฑ๏ธ
O(2^n * n^2)
2^n subsets to try, n^2 time to check distances and calculate sums
n
2n
โ Quadratic Growth
Space Complexity
O(n)
Space for recursion stack and storing current subset
n
2n
โก Linearithmic Space
28.5K Views
MediumFrequency
~35 minAvg. Time
890 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.