Bµi to¸n t×m c©y khung ng¾n nhÊt lµ mét bµi to¸n gÆp trong thùc tÕ : ThÝ dô : X©y dùng m¹ng d©y ®iÖn tho¹i nèi N thµnh phè sao cho 2 thµnh phè bÊt kú liªn lạc đợc với nhau và tổng đờng d[r]
Trang 1Phần 3 Cây - CÂy khung ngắn nhất
I / Định nghĩa :
Cây là đồ thị hữu hạn , vô hớng , liên thông , không có chu trình , có ít nhất 2 đỉnh
II / Tính chất :
1 - Định lý 1 :
Nếu H là cây có N đỉnh thì H có các tính chất sau đây :
a) Thêm vào H một cạnh nối 2 đỉnh bất kỳ không kề nhau , H sẽ xuất hiện chu trình b) Bớt đi 1 cạnh trong H thì H không liên thông
c) Giữa 2 đỉnh bất kỳ của H luôn tồn tại 1 đờng đi duy nhất ( vậy H là đồ thị đơn)
d) H có N-1 cạnh
2 - Định lý 2 :
Nêú đồ thị G liên thông có N đỉnh và N-1 cạnh thì G là cây
Vậy cây là đồ thị liên thông có chu số bằng 0 ( suy từ công thức Ơle )
3 - Ghi chú :
Từ 1 đồ thị có thể hình thành nhiều cây khác nhau ( gọi là các cây khung của đồ
thị ) Trong số các cây khung của đồ thị , có 1 cây đợc tạo ra một cách đơn giản nh sau :
nối 1 đỉnh với n-1 đỉnh còn lại !
Số cây khung của 1 đồ thị đầy đủ là N n-2 ( N số đỉnh )
Số cây khung của một đồ thị có hữu hạn đỉnh là một số hữu hạn ,nên luôn tìm đợc ít nhất
1 cây khung có tổng độ dài nhỏ nhất ( nguyên lý biên ) Ta gọi cây khung này là cây khung ngắn nhất
Bài toán tìm cây khung ngắn nhất là một bài toán gặp trong thực tế :
Thí dụ : Xây dựng mạng dây điện thoại nối N thành phố sao cho 2 thành phố bất kỳ liên
lạc đợc với nhau và tổng đờng dây điện ngắn nhất Đó là bài toán tìm cây khung ngắn nhất Ngợc lại : Xây dựng mạng dây điện thoại nối N thành phố sao cho 2 thành phố bất
kỳ liên lạc đợc với nhau và tổng độ tin cậy trên các đờng dây điện là lớn nhất Đó là bài toán tìm cây khung dài nhất
III / Thuật toán Prim tìm cây khung nhỏ nhất :
B
ớc 1 : Khởi trị - Lấy 1 đỉnh i tuỳ ý đa vào tập đỉnh của cây Khi đó tập đỉnh của cây là Đ
= {i } Tập cạnh của cây là C = ( Tập rỗng )
B
ớc 2 : Gán nhãn - Với mỗi đỉnh k không thuộc Đ , ta gán cho nó nhãn k(i ,d ) trong đó i
là tên đỉnh thuộc Đ ,kề với k , gần k nhất , còn d là khoảng cách giữa i và k Nếu trong
Đ không tìm đợc đỉnh i kề với k thì gán cho k nhãn k( 0 , )
B
ớc 3 : Kết nap - Chọn đỉnh k không thuộc tập Đ , có nhãn d nhỏ nhất , kết nạp k vào
Đ Vậy Đ = Đ + { k } Nhãn của k là k( i ,d ) thì kết nạp cạnh ( i , k ) vào tập cạnh C Vậy C = C + { cạnh ( i , k ) } Gọi đỉnh k vừa kết nạp là i0
Nếu số đỉnh của Đ bằng N thì kết thúc , còn không chuyển sang bớc 4
B
ớc 4 : Sửa nhãn - Với mọi đỉnh k cha thuộc Đ có nhãn là k( i, d ) mà k kề với i 0 - là đỉnh vừa đợc kết nạp vào tập đỉnh ở bớc 3 - ta sửa lại nhãn của k theo nguyên tắc sau : Gọi độ dài cung (i0 ,k ) là e
Nếu d > e thì đỉnh k có nhãn mới là k( i 0 , e )
Trang 2ThÝ dô :
File d÷ liÖu vµo : PRIM.INT
6
0 16 3 12 0 0
16 0 12 0 7 0
3 12 0 13 16 10
12 0 13 0 0 5
0 7 16 0 0 16
0 0 10 5 16 0
File d÷ liÖu ra : PRIM.OUT
( 1, 3)= 3 ( 3, 6)= 10 ( 6, 4)= 5 ( 3, 2)= 12 (
2, 5)= 7
Tong gia tri cay khung ngan nhat la 37
Uses Crt;
Const Fi = 'prim.txt';
Fo = 'prim.out';
Max = 200;
Var A : Array[1 Max,1 Max] of Byte;
D : Array[1 Max] of Boolean;
C : Array[0 Max] of record x1,x2 : Byte; end;
Nh : Array[1 Max] of record truoc,giatri : Byte; end;
N,dd,socanh : Byte;
{canh : Integer;}
{ -}
Procedure DocF; Var f : Text; i,j : Byte; Begin Assign(f,fi); Reset(f); Readln(f,n); For i:=1 to n do Begin
i
e=15 i0
Nh·n míi k (i0,15) +) i0 : võa kÕt n¹p vµo § , k : kh«ng thuéc §
i 0 (i0,10) k (i,23) 12
16 3 13 5
12 10
16
7 16
3 2
5
6
Trang 3For j:=1 to n do read(f,a[i,j]); Readln(f);
End;
Close(f);
End;
{ -}
Procedure Napdinh1;
Begin
Fillchar(d,sizeof(d),False);
d[1] := True;
dd := 1;
End;
{ -}
Function Min(xj : Byte): Byte;
Var xi,p,i : Byte;
Begin
xi := 0; p := 255;
For i:=1 to N do
If d[i] then
If (p>a[i,xj]) and (a[i,xj]>0) then Begin
xi := i; p := a[i,xj];
End;
Min := xi;
End;
{ -}
Procedure Gannhan;
Var xi,xj : Byte;
Begin
For xj:=1 to N do
If not d[xj] then
Begin
xi := Min(xj);
If (xi>0) and (A[xi,xj]>0) then Begin
nh[xj].truoc := xi;
nh[xj].giatri:= A[xi,xj]; End
Else
If xi=0 then
Begin
nh[xj].truoc := 0;
nh[xj].giatri:= 255;
End;
End;
End;
{ -}
Procedure Ketnapthem;
Var p,j,xj : Byte;
Begin
p := 255;
For j:=1 to n do
If not d[j] then
Begin
If (nh[j].giatri<p) then
Begin
xj := j;
p := nh[j].giatri;
End;
Trang 4End;
d[xj] := True;
Inc(socanh);
c[socanh].x1 := nh[xj].truoc;
c[socanh].x2 := xj;
dd := xj;
End;
{ -}
Procedure Suanhan;
Var xj : Byte;
Begin
For xj:=1 to N do
If (not D[xj]) and (A[xj,dd]>0) then
Begin
If Nh[xj].giatri>A[xj,dd] then
Begin
Nh[xj].truoc := dd;
Nh[xj].giatri:= A[xj,dd];
End;
End;
End;
{ -}
Procedure Hiencanh;
Var i,p : Byte;f : Text;
Begin
Assign(f,fo);
Rewrite(f);p:=0;
For i:=1 to n-1 do
Begin
p := A[c[i].x1,c[i].x2]+p;
Write(f,'(',c[i].x1:2,',',c[i].x2:2,')=',A[c[i].x1,c[i].x2]:3,' ':3); End;
Writeln(f);
Writeln(f,'Tong gia tri cay khung ngan nhat la ',p);
Close(f);
End;
{ -}
Procedure TT_Prim;
Var Ok : Boolean;
Begin
SoCanh := 0;
Fillchar(nh,sizeof(nh),0);
Napdinh1;
Gannhan;
Ok := False;
Repeat
Ketnapthem;
If Socanh=N-1 then Ok:= True
Else Suanhan;
Until Ok;
Hiencanh;
End;
{ -}
BEGIN
Clrscr;
DocF;
TT_Prim
END
Trang 5Phần 4
Tìm đờng đi ngắn nhất