Thuật toán Johnson

Thuật toán Johnson được Donald B. Johnson tìm ra năm 1977. Thuật toán Johnson là một thuật toán giải quyết bài toán đường đi ngắn nhất giữa mọi cặp đỉnh trong đồ thị có hướng, có trọng số và không có chu trình âm.  Nó hoạt động bằng cách sử dụng thuật toán Bellman – Ford để tính toán một phép biến đổi của đồ thị đầu vào loại bỏ tất cả các trọng số âm, cho phép thuật toán Dijkstra được sử dụng trên đồ thị đã biến đổi.

Bài toán 
Nếu đã tìm hiểu về Thuật toán Dijkstra và Thuật toán Floyd-Warshall thì chúng ta biết rằng với đồ thị không có trọng số âm thì thuật toàn Dijkstra sẽ có tốc độ xử lý nhanh nhất 

còn Floyd-Warshal thì tìm đường đi ngắn nhất giữa mọi cặp đỉnh trong thời gian . Mở rộng hơn nếu chúng ta áp dụng thuật toán Dijkstra (với Fibonacci Heap)  lần, ta sẽ thu được thuật toán nhanh hơn hẳn 

Vấn đề đặt ra là có tồn tại hay không thuật toán  tìm đường đi ngắn nhất giữa mọi cặp đỉnh trong đồ thị có hướng, có trọng số âm và không có chu trình âm?

Thuật toán Johnson được tạo ra để giải quyết vấn đề này.

Giới thiệu thuật toán 
Ý tưởng của thuật toán là từ đồ thị đã cho, tìm cách chuyển nó thành đồ thị có trọng số không âm rồi dùng thuật toán Dijkstra áp dụng cho từng đỉnh

Mô tả thuật toán 
Thuật toán Johnson có 4 bước cơ bản:

 Thêm vào  một đỉnh  và với mỗi , thêm cung  có trọng số 
 Áp dụng thuật toán Bellman-Ford tìm khoảng cách ngắn nhất  từ  tới mọi  và sử dụng khoảng cách đó làm thế năng của đỉnh , i.e, 
 Gán cho mỗi cung một trọng số mới.. Gọi đồ thị với trọng số mới là  ( là đồ thì có trọng số không âm)
 Áp dụng Dijkstra  lần cho đồ thị để tìm đường đi ngắn nhất giữa mọi cặp đỉnh trong. Gọi  lần lượt là khoảng cách từ  tơi  trong  và . độ lệch của đường đi ngắn nhất từ  tới  chính là  Từ đó suy ra: .

Mô tả theo cách nông dân thì:

 Thêm một đỉnh  vào đồ thị , có cạnh đến bất kỳ đỉnh nào của  cũng được và  có trọng số là 0.(ở hình bên dưới là đỉnh q)
 Dùng thuật toán Bellman-Ford, tìm đường đi từ  đến các đỉnh còn lại. (kết quả được đồ thị thứ 2 ở hình bên dưới)
 Thay đổi trọng số của đồ thị đã cho  bằng đồ thị mới  có trọng số không âm bằng cách, Mỗi cạnh từ u đến v có trọng số  thay bằng giá trị mới .(kết quả được đồ thị thứ 3 ở hình bên dưới)
 Dùng thuật toán Dijsktra với đồ thị

Chú thích 

Giải thuật tìm kiếm
Giải thuật lý thuyết đồ thị