Nguồn đề bài: http://vn.spoj.com/problems/FLOYD/
1. Đề bài FLOYD Dijkstra căn bản
Cho đơn đồ thị vô hướng N đỉnh và M cạnh, trọng số các cạnh đều nguyên dương. Có 2 loại câu hỏi :
0 u v : Cho biết đường đi ngắn nhất từ u tới v có độ dài là bao nhiêu.
1 u v : Hãy chỉ ra 1 đường đi ngắn nhất từ u => v
Bài cơ bản này nhằm kiểm tra kỹ năng xây dựng các module chương trình con dành cho truy vết 1 cách hợp lý, sử dụng nhuần nhuyễn chương trình con, lời gọi hàm .
Input
Dòng 1 : 3 số nguyên N , M , K . ( 1 ≤ N ≤ 100 , 1 ≤ M ≤ N*(N-1)/2 , 1 ≤ K ≤ 1000 )
M dòng tiếp theo , dòng thứ i gồm 3 số nguyên dương u , v , c cho biết cạnh (u,v) có trọng số là c ( 1 ≤ c ≤ 10000 )
K dòng tiếp theo là K câu hỏi , dòng thứ j sẽ có định dạng như đã nêu ở trên .
Output
Ứng với mỗi câu hỏi trong K câu hỏi thì ta phải trả lời trên mỗi dòng như sau .
Câu hỏi 0 u v : Ghi ra 1 số nguyên duy nhất là độ dài đường đi ngắn nhất từ u -> v.
Câu hỏi 1 u v : Ghi ra số đầu tiên là số X là số đỉnh trên đường đi ngắn nhất này , tiếp đó ghi ra X số là chỉ số các đỉnh theo thứ tự xuất hiện trên hành trình .
Example
Input:
3 3 2
1 2 3
2 3 1
1 3 5
0 1 2
1 1 3
Output:
3
3 1 2 3
2. code tham khảo Dijkstra, Floyd (pascal và c++)
a. Code Dijkstra Pascal
const fi=''; nmax=100; vc=100000;//high(longint); type data=longint; var f:text; n,m,k:data; A:array[0..nmax+1,0..nmax+1] of data; D:array[0..nmax+1] of data; free:array[0..nmax+1] of boolean; trace:array[0..nmax+1] of data; luu:array[0..nmax+1] of data; spt:data; procedure dijkstra(s,t:data); var i,j,u,v,min:data; begin for i:=1 to n do begin free[i]:=true; d[i]:=a[s,i]; trace[i]:=s; end; repeat min:=vc; u:=0; for i:=1 to n do if (free[i]) and (d[i]<min) then begin min:=d[i]; u:=i; end; if (u=0) or (u=t) then break; free[u]:=false; for v:=1 to n do begin if (free[v]) and (d[v]>d[u]+a[u,v]) then begin d[v]:=d[u]+a[u,v]; trace[v]:=u; end; end; until FALSE; end; procedure truyvet(v:data); var x:data; i:data; begin if trace[v]<>0 then begin truyvet(trace[v]); inc(spt); luu[spt]:=v; end else begin inc(spt); luu[spt]:=v; end; end; procedure docfile; var i,j,u,v,c,tl:data; begin assign(f,fi); reset(f); readln(f,n,m,k); for i:=1 to n do for j:=1 to n do if i=j then a[i,j]:=0 else a[i,j]:=vc; for i:=1 to m do begin readln(f,u,v,c); a[u,v]:=c; a[v,u]:=c; end; for i:=1 to k do begin readln(f,tl,u,v); if tl=0 then begin dijkstra(u,v); writeln(d[v]); end else begin dijkstra(u,v); if u<>v then begin spt:=0; trace[u]:=0; truyvet(v); write(spt,' '); for j:=1 to spt do write(luu[j],' '); writeln; end else writeln('2 ',u,' ',v); end; end; close(f); end; begin docfile; readln; end.
b. Code Dijkstra c++
#include <bits/stdc++.h> using namespace std; const int maxn=100; const int maxd=10e6; int n,m,k; int a[maxn][maxn]; void Init() { scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]=maxd; int u,v,c; for (int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&c); a[u][v]=c; a[v][u]=c; } } void Solve() { while(k--) { int t,u, v; scanf("%d%d%d",&t,&u,&v); vector<int> L(n+2,0); vector<int> Prev(n+2,0); vector<int> Visit(n+2,0); for (int i=1;i<=n;i++) L[i]=maxd; L[u]=0; while(1) { int u=0; int min1=maxd; for (int i=1;i<=n;i++) { if(!Visit[i] && L[i]<min1) { min1=L[i]; u=i; } } if(u==0 || u==v) break; Visit[u]=1; for (int i=1;i<=n;i++) { if(!Visit[i] && L[i]>L[u]+a[u][i]) { L[i]=L[u]+a[u][i]; Prev[i]=u; } } } if(t==0) { printf("%dn",L[v]); } else { stack<int> st; while(v != u) { st.push(v); v=Prev[v]; } printf("%d %d ",st.size()+1,u); while(!st.empty()) { printf("%d ",st.top()); st.pop(); } printf("n"); } } } int main() { Init(); Solve(); }
c. Code Floyd Pascal
const INP = '' ; OUT = '' ; maxn = 100 ; maxc = 10000000 ; var n , m , cau_hoi : integer ; a : array[1..maxn,1..maxn] of longint ; trace : array[1..maxn,1..maxn] of byte ; fi , fo : text ; procedure answer ; var i , j , u , v , pt , loai : integer ; l : array[1..maxn] of integer ; procedure truy_vet( u , v : integer ) ; var k : integer ; begin k := trace[u,v] ; if k = 0 then begin inc( pt ) ; l[pt] := v ; exit ; end ; truy_vet( u , k ) ; truy_vet( k , v ) ; end ; begin for i := 1 to cau_hoi do begin read( fi , loai , u , v ) ; if loai = 0 then writeln( fo , a[u,v] ) { cau hoi loai 0 } else { cau hoi loai 1 } if a[u,v] < 0 then writeln( fo , -1 ) else begin pt := 1 ; l[1] := u ; truy_vet( u , v ) ; write( fo , pt ) ; for j := 1 to pt do write( fo , ' ', l[j] ) ; writeln( fo ) ; end ; end ; end ; procedure process ; var k , u, v : longint ; begin for k := 1 to n do { Floyd } for u := 1 to n do for v := u + 1 to n do if a[u,v] > a[u,k] + a[k,v] then begin a[u,v] := a[u,k] + a[k,v] ; a[v,u] := a[u,v] ; trace[u,v] := k ; trace[v,u] := k ; end ; for u := 1 to n do for v := 1 to n do if a[u,v] = maxc then a[u,v] := -1 ; { Khong ton tai duong di } end ; procedure nhapdl ; var i , j, u , v , val : longint ; begin read( fi , n , m , cau_hoi ) ; for i := 1 to n do for j := 1 to n do a[i,j] := maxc ; for i := 1 to m do begin read( fi , u , v , val ) ; a[u,v] := val ; a[v,u] := val ; end ; for i := 1 to n do a[i,i] := 0 ; end ; procedure mofile ; begin assign( fi , INP ) ; reset( fi ) ; assign( fo , OUT ) ; rewrite( fo ) ; end ; procedure dongfile ; begin close( fi ) ; close( fo ) ; end ; BEGIN mofile ; nhapdl ; process ; answer ; dongfile ; END.
Thuật toán tìm đường đi ngắn nhất, thuat toan floyd, dijkstra c++ pascal toan roi rac, floyd’s algorithm, dijkstra algorithm