DSA

Link-Cut Trees in Java: Dynamic Tree Connectivity

Master Link-Cut Trees (LCT) in Java. Learn how to maintain a forest of trees and perform path queries and connectivity updates in O(log N) time using splay trees.

Sachin Sarawgi·April 21, 2026·4 min read
#dsa#java#tree#link-cut tree#lct#dynamic connectivity#interview preparation#algorithms

While Heavy-Light Decomposition (HLD) is excellent for static trees, it struggles with dynamic trees where edges are frequently added or removed. Link-Cut Trees (LCT) are the solution to this problem, allowing us to maintain a forest of trees and perform path operations in amortized $O(\log N)$ time.

The Core Concept: Preferred Paths and Splay Trees

LCT decomposes each tree in the forest into a set of disjoint paths called preferred paths. Each preferred path is stored in an auxiliary data structure—typically a Splay Tree—where nodes are keyed by their depth in the original tree.

  1. Access(v): The fundamental operation that makes the path from the root to node $v$ a preferred path.
  2. Link(u, v): Adds an edge between node $u$ and node $v$, connecting two previously disjoint trees.
  3. Cut(v): Removes the edge between node $v$ and its parent, splitting a tree into two.
  4. FindRoot(v): Identifies the root of the tree containing node $v$, useful for checking connectivity.

Link-Cut Tree Implementation in Java (Simplified)

public class LinkCutTree {
    static class Node {
        Node left, right, parent;
        boolean reverse;
        int value, sum; // Example for path sum queries

        Node(int v) {
            this.value = this.sum = v;
        }

        boolean isRoot() {
            return parent == null || (parent.left != this && parent.right != this);
        }

        void pushDown() {
            if (reverse) {
                reverse = false;
                Node temp = left; left = right; right = temp;
                if (left != null) left.reverse = !left.reverse;
                if (right != null) right.reverse = !right.reverse;
            }
        }

        void pushUp() {
            sum = value;
            if (left != null) sum += left.sum;
            if (right != null) sum += right.sum;
        }
    }

    private void rotate(Node x) {
        Node y = x.parent, z = y.parent;
        if (!y.isRoot()) {
            if (z.left == y) z.left = x;
            else z.right = x;
        }
        x.parent = z;
        if (y.left == x) {
            y.left = x.right;
            if (x.right != null) x.right.parent = y;
            x.right = y;
        } else {
            y.right = x.left;
            if (x.left != null) x.left.parent = y;
            x.left = y;
        }
        y.parent = x;
        y.pushUp();
        x.pushUp();
    }

    private void splay(Node x) {
        while (!x.isRoot()) {
            Node y = x.parent, z = y.parent;
            if (!y.isRoot()) y.pushDown();
            x.pushDown();
            if (!y.isRoot()) {
                if ((z.left == y) == (y.left == x)) rotate(y);
                else rotate(x);
            }
            rotate(x);
        }
        x.pushDown();
    }

    public void access(Node x) {
        Node last = null;
        for (Node curr = x; curr != null; curr = curr.parent) {
            splay(curr);
            curr.right = last;
            curr.pushUp();
            last = curr;
        }
        splay(x);
    }

    public void makeRoot(Node x) {
        access(x);
        x.reverse = !x.reverse;
        x.pushDown();
    }

    public void link(Node x, Node y) {
        makeRoot(x);
        x.parent = y;
    }

    public void cut(Node x, Node y) {
        makeRoot(x);
        access(y);
        if (y.left == x && x.right == null) {
            y.left = x.parent = null;
            y.pushUp();
        }
    }
}

Link-Cut Tree vs. Heavy-Light Decomposition

Feature Link-Cut Tree Heavy-Light Decomposition
Tree Structure Dynamic (Link/Cut) Static
Time Complexity Amortized $O(\log N)$ $O(\log^2 N)$
Implementation Very Complex (Splay Trees) Moderate (Segment Trees)
Best For Dynamic connectivity problems Static path queries

Real-World Applications

  1. Network Topology: Managing dynamic connections in a network and finding shortest paths or capacities.
  2. Dynamic Graph Algorithms: Solving problems like dynamic Minimum Spanning Tree (MST).
  3. Cluster Management: Tracking connectivity in distributed systems where nodes and links are volatile.

Summary

The Link-Cut Tree is one of the most sophisticated data structures in computer science. By combining the flexibility of Splay Trees with the concept of preferred paths, it achieves near-optimal performance for dynamic tree operations. While its implementation is a significant challenge, its ability to handle structural changes in logarithmic time makes it an invaluable tool for high-performance systems.

📚

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: