Create Components With Same Value

hard tree dfs math enumeration

Problem

An undirected tree has n nodes with values nums[i] and an edge list. Delete some edges so the tree splits into components that all have the same value sum. Return the maximum number of edges you can delete.

Inputnums = [6,2,2,2,6], edges = [[0,1],[1,2],[1,3],[3,4]]
Output2
Total is 18. Cutting into 3 components each summing to 6 ({0},{1,2,3},{4}) removes 2 edges.

def components_with_same_value(nums, edges):
    n = len(nums)
    g = [[] for _ in range(n)]
    for a, b in edges:
        g[a].append(b); g[b].append(a)
    total = sum(nums)
    best_max = max(nums)
    def can(target):
        ok = [True]
        def dfs(u, p):
            s = nums[u]
            for v in g[u]:
                if v != p:
                    s += dfs(v, u)
            if s == target:
                return 0
            if s > target:
                ok[0] = False
            return s
        return dfs(0, -1) == 0 and ok[0]
    for parts in range(n, 0, -1):
        if total % parts: continue
        target = total // parts
        if target < best_max: continue
        if can(target):
            return parts - 1
    return 0
function componentsWithSameValue(nums, edges) {
  const n = nums.length;
  const g = Array.from({length: n}, () => []);
  for (const [a, b] of edges) { g[a].push(b); g[b].push(a); }
  const total = nums.reduce((x, y) => x + y, 0);
  const bestMax = Math.max(...nums);
  function can(target) {
    let ok = true;
    function dfs(u, p) {
      let s = nums[u];
      for (const v of g[u]) if (v !== p) s += dfs(v, u);
      if (s === target) return 0;
      if (s > target) ok = false;
      return s;
    }
    return dfs(0, -1) === 0 && ok;
  }
  for (let parts = n; parts >= 1; parts--) {
    if (total % parts) continue;
    const target = total / parts;
    if (target < bestMax) continue;
    if (can(target)) return parts - 1;
  }
  return 0;
}
import java.util.*;
class Solution {
    List<Integer>[] g; int[] nums; int target; boolean ok;
    public int componentValueSum(int[] nums, int[][] edges) {
        int n = nums.length; this.nums = nums;
        g = new List[n];
        for (int i = 0; i < n; i++) g[i] = new ArrayList<>();
        for (int[] e : edges) { g[e[0]].add(e[1]); g[e[1]].add(e[0]); }
        int total = 0, bestMax = 0;
        for (int v : nums) { total += v; bestMax = Math.max(bestMax, v); }
        for (int parts = n; parts >= 1; parts--) {
            if (total % parts != 0) continue;
            target = total / parts;
            if (target < bestMax) continue;
            ok = true;
            if (dfs(0, -1) == 0 && ok) return parts - 1;
        }
        return 0;
    }
    int dfs(int u, int p) {
        int s = nums[u];
        for (int v : g[u]) if (v != p) s += dfs(v, u);
        if (s == target) return 0;
        if (s > target) ok = false;
        return s;
    }
}
class Solution {
public:
    vector<vector<int>> g; vector<int> nums; int target; bool ok;
    int dfs(int u, int p) {
        int s = nums[u];
        for (int v : g[u]) if (v != p) s += dfs(v, u);
        if (s == target) return 0;
        if (s > target) ok = false;
        return s;
    }
    int componentValueSum(vector<int>& nums_, vector<vector<int>>& edges) {
        int n = nums_.size(); nums = nums_;
        g.assign(n, {});
        for (auto& e : edges) { g[e[0]].push_back(e[1]); g[e[1]].push_back(e[0]); }
        int total = 0, bestMax = 0;
        for (int v : nums) { total += v; bestMax = max(bestMax, v); }
        for (int parts = n; parts >= 1; parts--) {
            if (total % parts != 0) continue;
            target = total / parts;
            if (target < bestMax) continue;
            ok = true;
            if (dfs(0, -1) == 0 && ok) return parts - 1;
        }
        return 0;
    }
};
Time: O(n · d(total)) Space: O(n)