main.go
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
package main

import "fmt"

type DSU struct {
	parent []int
	rank   []int
}

func NewDSU(n int) *DSU {
	parent := make([]int, n)
	rank := make([]int, n)
	for i := 0; i < n; i++ {
		parent[i] = i
	}
	return &DSU{parent: parent, rank: rank}
}

func (d *DSU) Find(x int) int {
	if d.parent[x] != x {
		d.parent[x] = d.Find(d.parent[x])
	}
	return d.parent[x]
}

func (d *DSU) Union(a, b int) bool {
	ra, rb := d.Find(a), d.Find(b)
	if ra == rb {
		return false
	}
	if d.rank[ra] < d.rank[rb] {
		ra, rb = rb, ra
	}
	d.parent[rb] = ra
	if d.rank[ra] == d.rank[rb] {
		d.rank[ra]++
	}
	return true
}

func (d *DSU) Connected(a, b int) bool {
	return d.Find(a) == d.Find(b)
}

func main() {
	d := NewDSU(6)
	d.Union(0, 1)
	d.Union(2, 3)
	d.Union(1, 2)

	fmt.Println("0 connected to 3?", d.Connected(0, 3))
	fmt.Println("4 connected to 5?", d.Connected(4, 5))
}

How It Works

Union-Find data structure with path compression and union by rank for near constant-time connectivity queries.

Initializes each node as its own parent; Find flattens the tree via path compression; Union merges roots based on rank to keep trees shallow; supports connected queries for any two nodes.

Key Concepts

  • 1Path compression drastically reduces future lookup depth.
  • 2Union by rank keeps the forest balanced.
  • 3Connected checks are O(1) after near-constant-time unions.

When to Use This Pattern

  • Dynamic connectivity problems in graphs or networks.
  • Kruskal's algorithm for minimum spanning tree construction.
  • Grouping elements in clustering or percolation simulations.

Best Practices

  • Reset or recreate the structure when the element set changes.
  • Avoid using out-of-range node identifiers.
  • Add tests for union and find invariants after mutations.
Go Version1.18+
Difficultybeginner
Production ReadyYes
Lines of Code53