Union-Find (Disjoint Set) — Struktur Data

Union-Find (juga dikenal sebagai Disjoint Set Union atau DSU) adalah struktur data yang melacak sekumpulan elemen yang terbagi dalam beberapa set yang tidak tum

Union-Find (juga dikenal sebagai Disjoint Set Union atau DSU) adalah struktur data yang melacak sekumpulan elemen yang terbagi dalam beberapa set yang tidak tumpang tindih.

Bayangkan kamu punya 10 orang, dan ingin cepat menjawab dua pertanyaan:

  1. "Apakah si A dan si B ada di grup yang sama?"
  2. "Gabungkan grup si A dan grup si B."

Union-Find menjawab keduanya dalam waktu hampir O(1) (secara teknis α(n) — inverse Ackermann, praktis konstan).

Dua operasi utama

Operasi Arti
find(x) Cari representatif (root) dari set yang berisi x
union(x, y) Gabungkan set x dan set y jadi satu

Dua elemen berada di set yang sama jika dan hanya jika find(x) === find(y).

Representasi: forest of trees

Setiap set direpresentasikan sebagai pohon terbalik — setiap node menunjuk ke parent-nya. Root adalah node yang parent-nya diri sendiri.

class UnionFind {
  constructor(n) {
    // Awalnya setiap elemen jadi root sendiri
    this.parent = Array.from({ length: n }, (_, i) => i);
    this.rank = new Array(n).fill(0); // perkiraan tinggi subtree
    this.count = n; // jumlah komponen terpisah
  }

  // find dengan path compression
  find(x) {
    if (this.parent[x] !== x) {
      this.parent[x] = this.find(this.parent[x]); // flatten saat traversal
    }
    return this.parent[x];
  }

  // union dengan union by rank
  union(x, y) {
    const rootX = this.find(x);
    const rootY = this.find(y);
    if (rootX === rootY) return false; // sudah di set yang sama

    if (this.rank[rootX] < this.rank[rootY]) {
      this.parent[rootX] = rootY;
    } else if (this.rank[rootX] > this.rank[rootY]) {
      this.parent[rootY] = rootX;
    } else {
      this.parent[rootY] = rootX;
      this.rank[rootX]++;
    }
    this.count--;
    return true;
  }

  connected(x, y) {
    return this.find(x) === this.find(y);
  }
}

Dua optimasi kunci

Dengan keduanya, amortized cost per operasi = O(α(n)), di mana α(n) ≤ 4 untuk semua n yang mungkin dipakai di praktik.

Kegunaan nyata

Masalah Cara pakai Union-Find
Kruskal MST Gabungkan edge satu per satu; skip edge yang sudah membuat cycle
Connected components Setelah union semua edge, count = jumlah komponen
Network connectivity "Apakah komputer A dan B terhubung?" — cek connected(A, B)
Friend circles Berapa grup pertemanan terpisah di social network?
Percolation Simulasi cairan merembes melalui grid

Rule of thumb: Kalau pertanyaannya "di grup mana?" atau "gabungkan grup", dan jarang perlu memisah kembali — Union-Find biasanya adalah jawaban optimal.

🎭 Analogi sehari-hari: Lomba balap kelompok di kampung. Awalnya tiap orang grup sendiri. Lalu pelan-pelan grup gabung. Pertanyaan tiap saat: "Saya satu grup sama Budi gak?" Daripada cek satu per satu (lambat), tiap grup punya ketua (root). Cek "ketua kita sama gak?" — kalau iya, satu grup. Kalau gabung 2 grup, ketua salah satu jadi anak ketua satunya. Itulah Union-Find.

💡 Kenapa α(n) ≤ 4? Inverse Ackermann tumbuh sangat lambat — bahkan untuk n = jumlah atom alam semesta, α(n) cuma ~4. Jadi praktiknya Union-Find ≈ O(1), tapi bukan benar-benar konstan secara matematik.

⚠️ Jebakan umum:

🎯 Union-Find vs BFS untuk komponen:

TL;DR: Union-Find = tracking grup terpisah dengan find/union ~O(1). Wajib path compression + union by rank. Foundation Kruskal MST dan banyak masalah connectivity.

Yang akan kamu pelajari