Dijkstra — Shortest Path — Algoritma

Dijkstra's Algorithm mencari jalur terpendek dari satu node (source) ke semua node lain di weighted graph dengan bobot non-negatif. Kalau BFS menghitung jarak…

Algoritma Dijkstra mencari jarak terpendek dari satu node ke semua node lain di graph berbobot. Graph-nya kota (node) yang disambung jalan (edge), dan bobot adalah angka di tiap jalan, misalnya panjangnya dalam km. BFS cuma menghitung jumlah jalan; Dijkstra menjumlahkan panjangnya, mirip aplikasi peta yang mencari rute terpendek dari rumahmu. Syaratnya satu: gak boleh ada bobot negatif.

🧪 Tebakan cepat: dari A ke B ada jalan langsung 4 km. Ada juga jalan memutar: A ke C 2 km, lalu C ke B 1 km. Mana yang lebih pendek? Tebak dulu, jawabannya ada di bagian "Ambil yang terdekat, lalu cek jalannya".

Ambil yang terdekat, lalu cek jalannya

Ada lima kota, A sampai E, dengan jalan dua arah: A-B 4 km, A-C 2, B-C 1, B-D 5, C-D 8, C-E 10, dan D-E 2. Dijkstra mencatat dist, jarak terpendek sejauh ini dari A, lalu mengulang dua langkah:

  1. Ambil kota yang belum selesai dengan dist terkecil. Jaraknya sekarang final.
  2. Cek tiap jalan dari kota itu. Kalau lewat sini lebih pendek dari jarak yang tercatat (atau belum ada catatan), ganti. Langkah ini disebut relaksasi.
Langkah Ambil (final) Yang berubah dist sesudahnya
1 A (0) B: 0 + 4 = 4, C: 0 + 2 = 2 A 0, B 4, C 2
2 C (2) B: 2 + 1 = 3, lebih pendek dari 4. D: 2 + 8 = 10. E: 2 + 10 = 12 B 3, D 10, E 12
3 B (3) D: 3 + 5 = 8, lebih pendek dari 10 D 8
4 D (8) E: 8 + 2 = 10, lebih pendek dari 12 E 10
5 E (10) (gak ada) selesai

Jarak B turun dari 4 jadi 3: jalan memutar lewat C lebih pendek. Itu jawaban tebakannya.

const graph = {
  A: [["B", 4], ["C", 2]],
  B: [["A", 4], ["C", 1], ["D", 5]],
  C: [["A", 2], ["B", 1], ["D", 8], ["E", 10]],
  D: [["B", 5], ["C", 8], ["E", 2]],
  E: [["C", 10], ["D", 2]],
};

function dijkstra(graph, start) {
  const dist = {};
  dist[start] = 0;
  const done = new Set();

  while (true) {
    let u = null; // kota belum selesai dengan jarak terkecil
    for (const node in dist) {
      if (!done.has(node) && (u === null || dist[node] < dist[u])) u = node;
    }
    if (u === null) break; // semua kota yang terjangkau sudah selesai
    done.add(u); // jarak u sekarang final

    for (const [v, w] of graph[u]) {
      const newDist = dist[u] + w;
      if (dist[v] === undefined || newDist < dist[v]) dist[v] = newDist; // relaksasi
    }
  }
  return dist;
}

console.log(dijkstra(graph, "A")); // { A: 0, B: 3, C: 2, D: 8, E: 10 }

Kenapa bobot negatif dilarang

Dijkstra berjanji: kota yang diambil, yang jaraknya terkecil di antara yang belum selesai, sudah final. Janji itu benar karena jalan lain ke kota itu pasti lewat kota yang jaraknya lebih besar, dan menambah bobot yang gak negatif cuma bikin makin panjang. Kalau ada bobot negatif, jalan memutar bisa jadi lebih pendek belakangan, padahal kotanya sudah dianggap final, jadi hasilnya bisa salah. Untuk graph dengan bobot negatif, pakai algoritma Bellman-Ford.

Kecepatan dan pilihan lain

Kode di atas menyisir semua kota tiap kali mencari yang terdekat. Untuk V kota itu sekitar V × V langkah, O(V²): kota dua kali lipat, kerjanya kira-kira empat kali lipat. Cukup untuk graph kecil. Untuk graph besar, kota terdekat diambil dari min-heap (priority queue), struktur data yang memberi isi terkecil dengan cepat: O((V + E) log V), dengan E jumlah jalan. log V itu kecil, untuk 1.000 kota sekitar 10.

Pilih algoritmanya dari bobotnya: semua jalan dihitung sama, pakai BFS. Bobot beda-beda dan gak ada yang negatif, pakai Dijkstra. Ada bobot negatif, pakai Bellman-Ford.

⚠️ Jebakan yang sering ketemu

TL;DR: Dijkstra mencari jarak terpendek dari satu kota ke semua kota lain di graph berbobot tanpa bobot negatif. Ulangi: ambil kota belum selesai dengan dist terkecil (jaraknya final), lalu relaksasi tiap jalannya: kalau dist[u] + w lebih kecil dari dist[v] (atau dist[v] belum ada), ganti. Jalan memutar bisa lebih pendek dari jalan langsung. Bobot negatif merusak janji "yang diambil sudah final", jadi pakai Bellman-Ford. Dengan sisir biasa O(V²), dengan min-heap O((V + E) log V).

Yang akan kamu pelajari