k>0 cho đỉnh vj khác với đỉnh kề của nó 6.Lặp lại đến khi tô màu xong
3.3 Bài toán đƣờng đi ngắn nhất
(Đề thi Olympic tin học trẻ Thành phố Hải Phòng năm 2012) a. Mô tả bài toán
Có N thành phố. Biết rằng đường đi giữa 2 thành phố bất kỳ (nếu có) đều là đường đi hai chiều. Sơ đồ mạng lưới giao thông của N thành phố này cho bởi ma trận trọng số đối xứng A[i,j], trong đó:
+ A[i,j] là độ dài đường đi từ thành phố i đến thành phố j.
+ A[i,j] = 0 nếu không có đường đi từ thành phố i đến thành phố j. + A[i,j] = A[j,i] và A[i,i]=0
+ A[i,j] nguyên, không âm.
- Dữ liệu vào: Cho file DDTOIUU.INP gồm N + 2 dòng
Dòng đầu là số N (N Nguyên dương, N 50)
Dòng i+1 (1 i N) ghi N số nguyên A[i, 1], A[i, 2],…, A[i, N].
Dòng N + 2 ghi 2 số P và Q - Dữ liệu ra: Ghi ra tệp DDTOIUU.OUT
Nếu có đường đi thì thông báo:
+ Dòng đầu cho biết độ dài đường đi ngắn nhất từ P đến Q + Dòng thứ i+1 là sơ đồ đường đi.
Nếu không có đường đi thông báo: + Không có đường đi từ P đến Q
Ví dụ
DDTOIUU.INP DDTOIUU. OUT
6 0 5 0 0 0 9 5 0 6 0 0 0 0 6 0 7 0 0 0 0 7 0 8 0 0 0 0 8 0 9 9 0 0 0 9 0 1 5
Đường đi ngắn nhất từ 1 đến 5 dài 18 1 6 5
61 0 2 3 0 0 2 3 0 2 0 5 0 3 5 0 0 0 0 0 0 2 4 b. Giải thuật
Gọi A[i,j] là độ dài đường đi ngắn nhất từ thành phố i đến thành phố j, thì độ dài đường đi ngắn nhất từ thành phố P đến thành phố Q là A[P, Q].
- Nếu có đường đi từ i đến k và từ k đến j (tức là A[i,k]>0 và A[k,j]>0) + Nếu A[i,j]=0 tức là không có đường đi trực tiếp từ i đến j.
+ Nếu có đường đi từ i đến j và A[i,j]>A[i,k]+A[k,j] thì gán lại A[i,j]:=A[i,k]+A[k,j];
- Độ dài đường đi ngắn nhất từ thành phố i đến chính nó thì = 0 nghĩa là A[i,j]=0
- Ta xét phương án A[i,j] gồm N dòng, N cột. Lúc đầu A[i,j] là độ dài đường đi từ i đến j (nếu A[i,j] 0), nếu không có đường đi từ i đến j thì A[i,j] = 0 nghĩa là mọi phần tử trên đường chéo chính đều = 0.
Gọi C[i,j] là điểm cần đi qua trên đường đi ngắn nhất từ i đến j Phép duyệt 3 vòng lặp lồng nhau
for k:=1 to N do for i:=1 to N do for j:=1 to N do
+ Nếu không có đường đi từ i đến j (A[i,j] = 0)
+ Nếu có đường đi từ i đến k và từ k đến j và độ dài A[i,j]>A[i,k]+A[k,j] thì gán lại A[i,j]:=A[i,k]+A[k,j]; và lưu C[i,j]:=k;
- Dựa vào kết quả của C[i,j] ta thấy C[i,j] = 0 thì A[i,j] không thay đổi còn C[i,j] = k là giá trị A[i,j] đã thay đổi tại bước thứ k. Khi đó giá trị A[P,Q] chính là độ dài ngắn nhất của đường đi từ P đến Q. Nếu giá trị của A[P,Q] = 0 tức là không
62
có đường đi từ P đến Q. Nếu có đường đi thì việc xác định đường đi được gọi đệ qui trong chương trình xác định đường đi: Procedure Xdduong(P,Q);
Thuật toán được mô tả chi tiết trong phụ lục 1 (Tên chương trình Duong_Di.Pas)