Tìm đườngđingắnnhất với định tuyến Dijkstra Bài viết này xin giới thiệu với các bạn mới làm quen với tin học và thuật giải một thuậttoán đơn giản nhưng lại có hiệu quả rất lớn trong việc tìm đườngđingắnnhấttrongđồ thị. Đó là thuậttoán Dijkstra. Đây là thuậttoán đã đăng tải trên tạp chí tin học & nhà trường từ những số đầu tiên nhưng bài viết này sẽ đăng tải đầy đủ về bài toán, phương thức đưa ra thuật giải cũng như đoạn chương trình đầy đủ. Rất thích hợp với những bạn mới làm quen với những thuậttoán kinh điển. Dijkstra là thuậttoán định tuyến đơn giản để tìmđườngđingắnnhất giữa 2 điểm bất kỳ. Không mất tính tổng quát, ta coi mỗi điểm (nút mạng) là một đỉnh của một đồ thị, ta sẽ dùng thuậttoánDijkstra để giải quyết bài toántìmđườngđingắnnhất giữa 2 điểm như sau: Bài toán: Cho đồthị G với tập đỉnh V và tập các cạnh E (đồ thị có hướng hoặc vô hướng). Mỗi cạnh của đồthị được gán một nhãn (giá trị không âm), nhãn này còn được gọi là giá trị của cạnh. Cho trước một đỉnh xác định v, gọi là đỉnh nguồn. Tìm đườngđingắnnhất từ đỉnh v đến các đỉnh còn lại của G. (Tức là tìmđườngđi từ v đến các đỉnh còn lại với tổng các giá của các cạnh trên đườngđi là nhỏ nhất). Nếu như đồthị có hướng thìđườngđi này là đườngđi có hướng. Thuậttoán Dijkstra: Ta có thể giải bài toán bằng cách xác định một tập hợp S chứa các đỉnh mà khoảng cách ngắnnhất từ nó đến đỉnh nguồn v đã biết. Khởi đầu S = { V }. Sau đó tại mỗi bước ta sẽ thêm vào S các đỉnh mà khoảng cách từ nó đến v là ngắn nhất. Với giả thiết rằng mỗi cung có một giá trị không âm thì ta luôn luôn tìm được một đườngđingắnnhất như vậy mà chỉ đi qua các đỉnh đã tồn tại trong S. Ðể dễ dàng chi tiết hóa giải thuật, giả sử G có n đỉnh và nhãn trên mỗi cung được lưu trong mảng C, tức là C[i, j] bằng giá trị(có thể xem là độ dài) của cung (i, j). Nếu i và j không có cung nối thì ta cho C[i, j] =Ġ. Ta sẽ dùng một mảng D có n phần tử để lưu độ dài của đườngđingắnnhất từ v đến mỗi đỉnh của đồ thị. Khởi đầu thì giá trị này chính là độ dài cạnh (v, i), tức D[i] = C[v, i]. Tại mỗi bước của giải thuậtthì D[i] sẽ lưu độ dài đườngđingắnnhất từ đỉnh v đến đỉnh i, đườngđi này chỉ đi qua các đỉnh đã có trong S. Ðể cài đặt giải thuật dễ dàng, ta giả sử các đỉnh của đồthị được đánh số từ 1 đến n và đỉnh nguồn là đỉnh 1. Dưới đây là giải thuậtDijkstra để giải bài toán trên : <!--[if !supportLineBreakNewLine]--> <!--[endif]--> procedure Dijkstra; begin S := [1] ; { S chỉ chứa đỉnh nguồn } for i:=2 to n do D[i] := C[1, i] ; { Khởi đầu các giá trị cho D } for i:=1 to n - 1 do begin Lấy đỉnh w trong V - S sao cho D[w] là nhỏ nhất ; Thêm w vào S ; for mỗi đỉnh u thuộc V - S do D[u] := Min (D[u], D[w] + C[w, u]) ; end; end; <!--[if !supportLineBreakNewLine]--> <!--[endif]--> Nếu muốn lưu trữ lại các đỉnh trên đườngđingắnnhất để có thể xây dựng lại đườngđi này từ đỉnh nguồn đến các đỉnh khác, ta dùng một mảng P. Mảng này sẽ lưu P[u] = w với đỉnh u là đỉnh trước của đỉnh w trên đường đingắn nhất. Lúc khởi đầu ta cho P[u] = 1, với mọi u khác 1. Giải thuậtDijkstra ở trên sẽ được viết lại như sau : <!--[if !supportLineBreakNewLine]--> <!--[endif]--> procedure Dijkstra ; begin S := [1] ; { S chỉ chứa đỉnh nguồn } for i:=2 to n do begin D[i] := C[1, i] ; { Khởi đầu các giá trị cho D } P[i] := 1 ; { Khởi đầu các giá trị cho P } end ; for i:=1 to n - 1 do begin Lấy đỉnh w trong V - S sao cho D[w] là nhỏ nhất ; Thêm w vào S ; for mỗi đỉnh u thuộc V - S do if (D[w] + C[w, u] < D [u]) then begin D[u] := D[w] + C[w, u] ; P[u] := w ; end ; end; end; Ví dụ : Áp dụng giải thuậtDijkstra cho đồthị hình sau: <!--[if !supportLineBreakNewLine]--> procedure DijksTra; begin t:=false; t[u0]:=true; d[i]:=c[u0,i];{Neu khong co duongdithi d[i]=i’} k:=1;{Da ket nap duoc 1 dinh} while kdo begin {Tim min} min:=i’; for i:=1 to n do if (d[i]<MIN)and(not t[i])then begin u:=i; min:=d[u] end; t[u]:=true;{thêm u vao tập đỉnh} inc(k); {Tính lại đường đi} for i:=1 to n do if d[i]>d[u]+c[u,i] then if not((d[i]=i’)and(d[u]=i’)and(c[u,i]=i’)) then begin d[i]:=d[u]+c[u,i]; truoc[i]:=u end end; if d[v0]=i’ then KhongCoDuongDi else QuayLaiMangTruocDeTimDuong end; . giản nhưng lại có hiệu quả rất lớn trong việc tìm đường đi ngắn nhất trong đồ thị. Đó là thuật toán Dijkstra. Đây là thuật toán đã đăng tải trên tạp chí tin. đỉnh của một đồ thị, ta sẽ dùng thuật toán Dijkstra để giải quyết bài toán tìm đường đi ngắn nhất giữa 2 đi m như sau: Bài toán: Cho đồ thị G với tập đỉnh