DSA

Centroid Decomposition in Java: Solving Tree Path Problems

Master Centroid Decomposition in Java. Learn how to recursively divide a tree into subtrees to solve complex path-related queries in O(N log N) time.

Sachin Sarawgi·April 21, 2026·3 min read
#dsa#java#tree#centroid decomposition#divide and conquer#interview preparation#algorithms

When dealing with problems that involve paths in a tree (like "how many paths have a length exactly $K$?"), a simple DFS might take $O(N^2)$. Centroid Decomposition is a divide-and-conquer technique that reduces this complexity to $O(N \log N)$.

The Core Concept: The Centroid

A centroid of a tree is a node whose removal splits the tree into subtrees, each having at most $N/2$ nodes. Every tree has at least one (and at most two) centroids.

  1. Finding the Centroid: Use DFS to calculate subtree sizes and identify the node that satisfies the centroid property.
  2. Recursive Decomposition: Once the centroid is found, "remove" it and recursively decompose the resulting subtrees.
  3. Centroid Tree: This process creates a new tree structure (the Centroid Tree) with a height of at most $O(\log N)$.

Centroid Decomposition Implementation in Java

import java.util.*;

public class CentroidDecomposition {
    private int n;
    private List<Integer>[] adj;
    private boolean[] removed;
    private int[] subtreeSize;

    public CentroidDecomposition(int n, List<Integer>[] adj) {
        this.n = n;
        this.adj = adj;
        this.removed = new boolean[n];
        this.subtreeSize = new int[n];
        decompose(0, -1);
    }

    private void computeSubtreeSize(int u, int p) {
        subtreeSize[u] = 1;
        for (int v : adj[u]) {
            if (v != p && !removed[v]) {
                computeSubtreeSize(v, u);
                subtreeSize[u] += subtreeSize[v];
            }
        }
    }

    private int findCentroid(int u, int p, int totalSize) {
        for (int v : adj[u]) {
            if (v != p && !removed[v] && subtreeSize[v] > totalSize / 2) {
                return findCentroid(v, u, totalSize);
            }
        }
        return u;
    }

    private void decompose(int u, int p) {
        computeSubtreeSize(u, -1);
        int centroid = findCentroid(u, -1, subtreeSize[u]);
        
        // Process paths passing through the centroid
        processCentroid(centroid);

        removed[centroid] = true;
        for (int v : adj[centroid]) {
            if (!removed[v]) {
                decompose(v, centroid);
            }
        }
    }

    private void processCentroid(int centroid) {
        // Logic to solve the specific path problem
        // e.g., counting paths of length K using a frequency map
    }
}

Why use Centroid Decomposition?

Feature Centroid Decomposition Heavy-Light Decomposition
Primary Use Path counting/properties Path updates/queries
Complexity $O(N \log N)$ $O(N \log^2 N)$
Structure Recursive Divide & Conquer Path-based Partitioning
Best For Global path problems Dynamic path queries

Real-World Applications

  1. Network Analysis: Analyzing properties of all possible communication paths in a hierarchical network.
  2. Computational Biology: Studying structural properties of tree-like molecular structures.
  3. Competitive Programming: Solving advanced tree problems involving path lengths, weights, or specific node properties.

Summary

Centroid Decomposition is a brilliant application of the divide-and-conquer paradigm to tree structures. By ensuring that each step reduces the problem size by at least half, it provides a robust framework for solving complex path problems that would otherwise be computationally expensive. While the implementation requires careful handling of subtree sizes and recursion, the efficiency it brings to tree algorithms is unparalleled.

📚

Recommended Resources

Java Masterclass — UdemyBest Seller

Comprehensive Java course covering Java 17+, OOP, concurrency, and modern APIs.

View Course
Effective Java, 3rd EditionMust Read

Joshua Bloch's classic guide to writing clear, correct, and efficient Java code.

View on Amazon
Java Concurrency in Practice

The authoritative book on writing thread-safe, concurrent Java programs.

View on Amazon

Practical engineering notes

Get the next backend guide in your inbox

One useful note when a new deep dive is published: system design tradeoffs, Java production lessons, Kafka debugging, database patterns, and AI infrastructure.

No spam. Just practical notes you can use at work.

Sachin Sarawgi

Written by

Sachin Sarawgi

Engineering Manager and backend engineer with 10+ years building distributed systems across fintech, enterprise SaaS, and startups. CodeSprintPro is where I write practical guides on system design, Java, Kafka, databases, AI infrastructure, and production reliability.

Found this useful? Share it: