FLOYD spoj – Floyd hoặc Dijkstra ( Cơ bản )

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

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *