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:2
💡 Note:We can invert node 1, which changes the subtree rooted at node 1. Original values [-2,-3,4] in the subtree become [2,3,-4]. The final tree values are [1,2,3,-4] with sum = 1 + 2 + 3 + (-4) = 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.
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
✓
Brute Force (Try All Combinations)
⏱️ Time: O(2^n * n^2)
Space: O(n)
Generate all possible subsets of nodes to invert, check if each subset satisfies the distance constraint, and find the one that gives maximum sum.
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>
#define MAX_N 20
static int graph[MAX_N][MAX_N];
static int children[MAX_N][MAX_N];
typedef struct {
int graphSize[MAX_N];
int parent[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 = graph[node][i];
if (neighbor != par) {
children[node][s->childrenSize[node]] = neighbor;
s->childrenSize[node]++;
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, 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 (nums[0] >= 0) ? nums[0] : -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];
graph[u][s.graphSize[u]] = v;
s.graphSize[u]++;
graph[v][s.graphSize[v]] = u;
s.graphSize[v]++;
}
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() {
printf("Solution\n");
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.