1. Trang chủ
  2. » Công Nghệ Thông Tin

Thuật toán Prim - Kruscal

3 1,6K 24
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 3
Dung lượng 36,5 KB

Nội dung

Thuật toán Prim - Kruscal

Trang 1

Thuật toán Prim - Kruscal

Đào Đức Minh

Bài toán: Cho một đồ thị vô hướng Hãy tìm cây bao trùm ngắn nhất (Tức là tổng các

trọng số các cạnh của cây là nhỏ nhất)

Giới hạn:

INPUT:

Dòng đầu: Gồm 2 số n,d: (n,d thuộc [0;100]), n là số đỉnh, d: Số cạnh

D dòng tiếp theo: Mỗi dòng gồm các số i,j,s

+ Cho biết trọng số cạnh i,j là s (i,j là số hiệu đỉnh)

OUTPUT:

- Dòng đầu: Gồm 1 số m duy nhất cho biết số cạnh của cây (luôn bằng (n-1))

- m (hay (n-1)) dòng tiếp theo: Mỗi dòng gồm các số a,b,s: Cho biết đỉnh a nối với đỉnh b

có trọng số cạnh ab là s

(n-1) dòng tiếp theo này cho biết các cạnh của cây

- Dòng cuối: T cho biết tổng trọng số của cây bao trùm ngắn nhất

- Nếu không liên thông thì xuất ″đồ thị không liên thông″

*) Giải thuật:

Có lẽ thuật toán Prim và Kruscal đã quen thuộc để giải loại bài toán này (Đã từng được giới thiệu trên báo THNT) , Nhưng mỗi thuật toán tôi lại cảm thấy không được tối ưu cho lắm vì các bước cần giải quyết khá phức tạp

*) Thuật toán Prim: Tư tưởng chủ đạo là chọn cạnh, mỗi lần chọn cạnh lại phải kiểm tra

có tạo chu trình hay không, nếu cạnh ấy có tạo chu trình thì loại bỏ cạnh ấy

Thuật toán Kruscal: Tư tưởng chủ đạo là chọn đỉnh, phải chọn đỉnh không ở trong tập

đỉnh đã chọn, có cung nối đỉnh đó với đỉnh đã chọn và có trọng số là nhỏ nhất

Các bước trong thuật toán trên khá phức tạp, tốn kém thời gian, khi dữ liệu quá lớn thì có

lẽ đó là chưa là thuật toán tốt Em đã nghĩ ra thuật toán kết hợp tinh hoa của hai thuật toán trên trở thành ″Thuật toán Prim − Kruscal″

Các bước của thuật toán:

Bước 1 Sắp xếp các cạnh từ nhỏ đến lớn theo trọng số (Dùng kiểu record), Chọn cạnh

đầu tiên

Bước 2 Tìm cạnh tiếp theo: cạnh được chọn phải thoả: 1 đỉnh ở trong tập hợp đỉnh đã

chọn và một đỉnh ngoài tập hợp đỉnh đã chọn và cạnh đó chưa được chọn

Bước 3: Trở lại đầu dãy cạnh đã sắp xếp

Trở lại bước 2 và chỉ thoát khi chọn đủ (n-1) cạnh hoặc chưa chọn đủ (n-1) cạnh nhưng không thể chọn thêm cạnh nữa (trường hợp này đồ thị không liên thông)

*) Ví dụ minh hoạ: Gọi T là tập các đỉnh đã chọn, C là tâp các cạnh đã chọn

Trang 2

Bước 1 Sắp xếp các cạnh theo chiều tăng của trọng số:

(1,2) (4,3) (3,5) (4,5) (1,4) (1,5) (2,5)

Trọng số 1 1 2 2 3 4 5

Chọn cạnh đầu tiên: (1,2) Khi đó, cạnh (1,2) đã chọn, đỉnh1,2 đã chọn C= { (1,2)}, T= {1,2}

Bước 2 Chọn cạnh tiếp theo: Duyệt từ đầu dãy: (1,2) đã chọn ; (4,3) chưa chọn nhưng

không thỏa: có 1 đỉnh trong, 1 đỉnh ngoài tập T; (3,5) không chọn được với lý do tương tự; (4,5) không chọn, (1,4) : cạnh này chưa chọn và có một đỉnh trong tập T, 1 đỉnh ngoài tập T nên chọn Khi đó:

C={(1,2), (1,4)}

T={1,2,4}

Bước 3 - Kiểm tra đủ (n-1) cạnh trong C chưa hoặc không còn có thể chọn cạnh tiếp hay

không, khi đó thoát

Trở lại đầu dãy trỏ lại bước 2

Bước 2: Duyệt lại từ đầu:

(1,2): đã có trong tập C nên không chọn, (4,3): chưa chọn, 1 đỉnh trong, 1 đỉnh ngoài T nên chọn Khi đó:

C={(1,2), (4,3), (1,4)}

T={1,2,4,3}

Cứ tiếp tục đến khi kết thúc (kiểm tra kết thúc ở bước 3)

Chương trình:

Type canh: record

d1,d2,d: word;

chon: Boolean;

end;

var a: array[1 10000] of canh;

v: array[1 10000] of boolean;

+) canh: d1,d2: 2 đỉnh của các cạnh, d: trọng số

+) mảng cạnh: a

+) v: v[i]=true khi và chỉ khi i thuộc T

+) cạnh có thành phần chọn: cho biết chọn hay không canh[i]

Với khai báo trên:

{Bước 1: Sắp xếp}

for i:=1 to m-1 do

for j:=1 to m do

If a[i].d>a[j].d then

Trang 3

Begin

tam: a[i];

a[i]:=a[j];

a[j]:=tam;

end;

{Chọn cạnh đầu tiên}

a[1].chon:= true; v[[a[1].d1]:=true; v[a[1].d2]:=true;

{Bước 2, bước 3}

Repeat

I:=1; inc(spt);

While (a[i].chon= true) or not (v[a[i].d1) xor v[a[i].d2]) and (i<=m) do inc(i);

If (i<=m) then

Begin

a[i].chon:=true;

v[a[i].d1]:=true;

v[a[i].d2]:=true;

end;

Until (spt=n-1) or (i>m);

{Xuất kết quả}

If (i<=m) then

Begin

For i:=1 to m do

If a[i].chon then

Write(fo, a[i].d1,′ ′, a[i].d2);

End

Else write(fo,′ Do thi khong lien thong′);

Ngày đăng: 11/09/2012, 15:24

TỪ KHÓA LIÊN QUAN

w