Các thuật toán tìm cây bao trùm

Một phần của tài liệu Một số vấn đề ứng dụng của đồ thị trong tin học (Trang 68 - 73)

II. CÂY BAO TRÙM

2. Các thuật toán tìm cây bao trùm

Xét đồ thị G = <X, U> liên thông có n đỉnh, ta có các thuật toán tìm cây bao trùm như sau:

2.1 Thuật toán theo lý thuyết

Giả sử G không có chu trình thì nó là một cây và cũng chính là cây bao trùm của nó. Nếu G có chu trình thì ở 1 chu trình đơn nào đó bỏ đi 1 cạnh đồ thị vẫn liên thông. Nếu G còn chu trình đơn thì bỏ tiếp 1 cạnh nữa ... cho đến khi không còn chu trình thì ta được đồ thị mới G' nhận được từ G và G' chính là 1 cây bao trùm của G.

Thuật toán trên chỉ có ý nghĩa lý thuyết vì khi số đỉnh lớn, chu trình lớn thì việc kiểm tra chu trình đối với máy tính đòi hỏi nhiều tính toán

2.2 Thuật toán tìm kiếm ưu tiên chiều sâu và chiều rộng

Rất nhiều thuật toán trên đồ thị được xây dựng dựa trên cơ sở duyệt tất cả các đỉnh của đồ thị sao cho mỗi đỉnh của nó được thăm đúng 1 lần, trong mục này ta sẽ đề cập tới 2 thuật toán rất cơ bản của đồ thị về thăm đỉnh theo nguyên tắc trên. Đó là thuật toán tìm kiếm theo chiều sâu và chiều rộng, chúng được sử dụng để tìm cây bao trùm của đồ thị, ngoài ra chúng còn được sử dụng trong các thuật toán tìm đường đi, tìm các thành phần liên thông, kiểm tra tính liên thông...

Trước khi đi vào 2 thuật toán, ta sẽ đề cập tới 1 yếu tố cơ bản cấu thành nên ý tưởng của nhiều thuật toán trong đồ thị đó là kỹ thuật quay lui. Đây là một kỹ thuật chính trong kỹ thuật lập trình có nhiều áp dụng, đặc biệt là áp dụng trong giải thuật tìm kiếm theo chiều sâu.

Nội dung của kỹ thuật quay lui có thể tóm tắt như sau: Dùng cây quyết định, còn lá thì biểu thị 1 lời giải có thể. Để tìm nghiệm bằng kỹ thuật quay lui, trước tiên tạo ra dãy quyết định (càng dài càng tốt) để tiến tới lời giải. Dãy quyết định có thể biểu thị một đường đi trong cây quyết định. Mỗi khi biết được không thể có lời giải từ bất kỳ dãy quyết định nào thì ta quay lui lại đỉnh cha của đỉnh hiện tại để hướng tới lời giải bằng dãy quyết định khác (nếu có thể). Thủ tục tiếp tục cho tới khi tìm được lời giải hoặc là kết luận không có lời giải.

Ví dụ cho 1 tập A = {1, 2, 3, 4} hãy tìm tập con của A gồm 3 phần tử sao cho tổng các phần tử của tập con này là 8.

Trước hết ta xây dựng cây quyết định cho bài toán này như sau:

Hình 2.2

Mỗi một nhánh là 1 phần tử của một tập con 3 phần tử nào đó của A, một dãy liên tiếp đường đi gồm 3 nhánh từ gốc tới lá là một tập con của A, mỗi một lá là tổng của một tập con.

Dãy quyết định cho lời giải như sau:

Đầu tiên đi theo các nhánh 1 - 2 - 3 tổng dãy ở lá là 6 . Không phải, quay lui một nhánh về nhánh 2 đi vào nhánh 4 được: 1 - 2 - 4 ở lá là 7 . Không đúng quay lại về nhánh 1 đi tiếp nhánh 3 và 4 được: 1 - 3 - 4 ở lá là 8, đây là nghiệm cần tìm, vậy tập con cần tìm là {1, 3, 4}

Đây cũng là bài toán tổ hợp có tính đệ quy, rõ ràng ở đây ta thấy được một áp dụng của cây trong kỹ thuật này.

2.2.2 Thuật toán tìm kiếm theo chiều sâu

Bước 1: Lấy một đỉnh bất kỳ làm gốc của cây bao trùm

Bước 2: Xây dựng đường đi từ đỉnh này bằng cách lần lượt ghép thêm các cạnh vào, sao cho mỗi cạnh ghép mới sẽ nối đỉnh cuối cùng trên đường đi với đỉnh chưa thuộc đường đi. Bước này thực hiện cho tới khi nào không thể ghép thêm cạnh mới được nữa.

6 7 8 9 1 2 3 4 3 4 2 3 4

Bước 3: Nếu đường đi chứa tất cả các đỉnh của đồ thị G thì đó chính là cây bao trùm cần tìm. Ngược lại thì thực hiện tiếp bước sau đây:

Bước 4: Quay lui lại đỉnh trước đỉnh cuối cùng của đường đi và xây dựng đường đi mới xuất phát từ đỉnh này. Nếu không xây dựng được đường đi mới từ đỉnh này thì lùi tiếp lại một đỉnh nữa trên đường đi và lặp lại quá trình xây dựng đường mới càng dài càng tốt.

Bước 5: Vì đồ thị là hữu hạn nên quá trình trên sau một số hữu hạn bước sẽ dừng lại và cho ta cây bao trùm của G = <X, U>

2.2.3 Thuật toán tìm kiếm theo chiều rộng:

Bước 1: Chọn một đỉnh làm gốc của cây

Bước 2: Ghép các cạnh liên thuộc với đỉnh này. Các đỉnh mới kề với gốc trong bước này đều nằm trên mức 1 của cây (với thứ tự tuỳ ý).

Bước 3: Tiếp tục với mỗi đỉnh ở mức 1, ta ghép các cạnh liên thuộc nó sao cho chúng không tạo nên chu trình. Các đỉnh kề được tạo ra ở bước này nằm trên mức 2 của cây.

Bước 4: Quá trình này sẽ dừng lại sau một số bước làm việc (do tập cạnh hữu hạn) và tất cả các đỉnh của đồ thị đều được ghép vào cây.

2.3 Các chương trình thể thiện cho các thuật toán:

2.3.1 Chương trình Pascal về thuật toán quay lui thể hiện cây ở hình 2.2

{ m là tổng của tập con, n là số phần tử của tập A, k là số phần tử của tập con của A} Var s: Array[1..10] Of Integer;

t,n,k,m,tg: Integer; Procedure Try(h,a:Integer); Var i: Integer;

Begin h:=h+1;

For i:=a to n-(k-h) do Begin s[h]:=i;

If h<k then Try(h,i+1) Else Begin

tg:=0;

For t:=1 to k do tg:= tg+ s[t];

if tg = 8 then For t:=1 to k do Write(s[t]:3); Writeln;

End; End;

End;

Begin

n:=4; k:=3; m:=8;

Try(0,1); {Tạo cây bắt đầu từ mức 0}

End.

2.3.2 Chương trình Pascal thể hiện thuật toán tìm kiếm ưu tiên theo chiều sâu và chiều rộng tìm cây bao trùm

Uses Crt;

Var mG,mT : Array[1..100,1..100] of Integer; {mG: mt ke cua do thi G

mT: mt ke cua cay bao trum cho dt G} n: Integer;

ChuaXet: Array[1..100] Of Boolean; Queue: Array[1..100] of Integer; tl: Char;

{Nhap du lieu cho do thi} Procedure NhapDl; Var i,j: Integer; Begin

{Nhap du lieu cho do thi G} Write('So dinh: '); Readln(n); For i:=1 to n do Begin ChuaXet[i]:=True; Queue[i]:=0;

For j:=i+1 to n do Begin

Write('a',i,j,' = '); Readln(mG[i,j]); mG[j,i]:=mG[i,j];

End; mG[i,i]:=0; End;

{Khoi tao du lieu cho cay bao trum} For i:=1 to n do

For j:=1 to n do mT[i,j]:=0; End;

Procedure Display; Var i,j: Integer;

Begin

Writeln('Ma tran ke cua do thi'); For i:=1 to n do Begin

For j:=1 to n do Write(mG[i,j]:3); Writeln;

End; Writeln;

Writeln('Ma tran ke cua cay bao trum'); For i:=1 to n do Begin

For j:=1 to n do Write(mT[i,j]:3); Writeln;

End; End;

{Thu tuc tim cay bao trum theo chieu sau} Procedure Dfs(v: Integer);

Var u: Integer; Begin

ChuaXet[v]:=False; {Dinh v da duoc tham} For u:=1 to n do

If (mG[v,u]<>0) and (ChuaXet[u]) then Begin {Duyet nhung canh ke voi v} mT[v,u]:=mG[v,u]; {Bo sung vao tap canh cua cay}

mT[u,v]:=mT[v,u]; Dfs(u);

End; End;

{Tim cay bao trum cua do thi theo chieu rong} Procedure Bfs(v: Integer);

Var i,u,First,Last: Integer; Begin

First:=1; Last:=1; Queue[Last]:=v;

ChuaXet[v]:=False; {Dinh v da duoc tham}

While First<=Last do Begin {Trong khi hang doi chua rong} u:=Queue[First]; Inc(First);

For i:=1 to n do

If (mG[u,i]<>0) and (ChuaXet[i]) then Begin {Duyet nhung canh ke voi v} mT[u,i]:=mG[u,i]; {Bo sung vao tap canh cua cay}

mT[u,i]:=mT[i,u]; ChuaXet[i]:=False; Inc(Last); Queue[Last]:=i; End; End; End; BEGIN NhapDl;

Write('Chon chieu sau hay chieu rong (s/r)? '); Readln(tl); If Upcase(tl) = 'S' then Dfs(1)

Else Bfs(1); Display; END.

Một phần của tài liệu Một số vấn đề ứng dụng của đồ thị trong tin học (Trang 68 - 73)

Tải bản đầy đủ (DOC)

(81 trang)
w