cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 113 of 218
Ideas this builds on
1D dynamic programming113 / 218

Sum of Distances in Tree

Picture

In A–B–C, the distance total from A is 3. Moving the root to B makes B and C one step closer and A one step farther. The new total is 3−2+1=2, without repeating every distance calculation.

Predict

Moving from parent u to child v, how many nodes get closer and how many get farther?

Walk through the small example

size[v] nodes get closer. All other n−size[v] nodes get farther. Therefore answer[v]=answer[u]+n−2*size[v].

Mental model and complete Python solution

Root the tree once at 0 and record parent-before-child order. Reverse that order to compute subtree sizes and each subtree’s total distance from its root. The root’s subtotal becomes its all-node answer. A second forward pass applies the reroot equation along each parent-child edge. Unique tree paths ensure that exactly one of the two sides becomes closer; there are no alternative cycle routes to complicate the distance change.

What the function promises: n vertices and edges form a connected undirected tree on 0..n−1. Return each vertex’s sum of unweighted distances to all vertices. Empty input returns [] as a helper extension.

def distance_sums(n, edges):
    if n == 0:
        return []
    graph = [[] for _ in range(n)]
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)
    parent = [-1] * n
    order = [0]
    for u in order:
        for v in graph[u]:
            if v != parent[u]:
                parent[v] = u
                order.append(v)
    size, subtotal = [1] * n, [0] * n
    for u in reversed(order[1:]):
        p = parent[u]
        size[p] += size[u]
        subtotal[p] += subtotal[u] + size[u]
    answer = [0] * n
    answer[0] = subtotal[0]
    for u in order[1:]:
        p = parent[u]
        answer[u] = answer[p] + n - 2 * size[u]
    return answer

assert distance_sums(3, [(0,1), (1,2)]) == [3,2,3]
assert distance_sums(4, [(0,1), (0,2), (0,3)]) == [3,5,5,5]
assert distance_sums(1, []) == [0]

Work and storage: O(V) time and space on a tree. Each edge participates in a constant number of updates. Both passes are iterative, so a long chain does not overflow recursion.

When to recognize it: Moving the root across an edge makes one whole side closer and the other side farther. Reuse the previous answer.

Check before applying it: The formula depends on a tree edge separating exactly two sides. Extra cycle edges destroy that partition argument.

Change one rule

Each tree edge has a positive length w rather than length one. Can the update be adapted?

See what changes

Yes. Along u→v, every node on v’s side gets w closer and every other node gets w farther. Use answer[v]=answer[u]+w*(n−2*size[v]), and multiply the upward size contribution by w as well.

Connect

tree summaries: A bottom-up pass finds subtree sizes and one distance total.

House Robber III: Small summaries let a parent reuse work done in its branches.

Problem reference: Sum of Distances in Tree (Hard). The walkthrough and Python solution above are original course material.