II. Cây bao trùm
2. Các thuật toán tìm cây bao trùm
2.3.1 Chương trình Pascal về thuật toán quay lui
{ 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}
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;
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.
3. Cây bao trùm bé nhất
3.1 Định nghĩa: Cho đồ thị n đỉnh G = <X, U> liên thông, n > 1. Mỗi cạnh u ẻ
U ta gán cho nó trọng số l(u). Giả sử G' = <X, U') là cây bao trùm của G. Ký hiệu gọi là trọng số hay là độ dài của G'.
Ký hiệu Ă là tập các cây bao trùm của G, khi đó nếu cây bao trùm g ẻ Ă thoả mãn l(g) = Min {l(g') / g' ẻ Ă} thì ta nói rằng g là cây bao trùm bé nhất trong G. 3.2 Thuật toán tìm cây bao trùm bé nhất
Cho đồ thị G = <X, U> với số đỉnh n tìm cây bao trùm bé nhất của G.
3.2.1 Thuật toán Kruskal
Thuật toán sẽ xây dựng tập cạnh của cây bao trùm nhỏ nhất theo từng bước. Trước hết sắp xếp các cạnh của đồ thị G theo thứ tự không giảm của độ dài. Bắt đầu từ tập cạnh của cây là rỗng , ở mỗi bước ta sẽ lần lượt duyệt trong danh sách cạnh đã sắp xếp, từ cạnh có độ dài nhỏ đến cạnh có độ dài lớn hơn, để tìm ra cạnh mà việc bổ sung nó vào tập cạnh của cây không tạo thành chu trình trong tập này. Thuật toán sẽ kết thúc khi ta thu được 1 tập cạnh gồm n - 1 cạnh. Cụ thể thuật toán có thể mô tả như sau:
- Bước 1: Chọn cạnh u1 thoả mãn l(u1) = min {l(u) : u ẻ U} đặt U1 = {u1}
- Bước 2: Chọn u2 thoả mãn : l(u2) = min{l(u) : u ẻ U\U1} đặt U2 = {u1, u2}
...
- Bước k + 1: Giả sử đã có tập Uk = {u1, u2, ..., uk} chọn uk+1 thoả mãn l(uk+1) = min(l(u) : u ẻ U\Uk}
đặt Uk+1 = Uk ẩ {uk+1}
Chú ý ở các bước, cạnh mới được chọn phải không lập thành chu trình với các cạnh đã chọn ở các bước trước. ∑∈ = ' ) ( ) ' ( U u u l G l
Thuật toán dừng lại lại ở bước thứ n - 1. Vậy cây T = <X, Un-1> tìm được là cây bao trùm ngắn nhất.
3.2.2 Thuật toán Prim
Thuật toán Prim còn được gọi là phương pháp lân cận gần nhất. Trong phương pháp này, bắt đầu từ một đỉnh s tuỳ ý của đồ thị, đầu tiên ta nối s với đỉnh lân cận gần nó nhất, chẳng hạn là đỉnh y. Nghĩa là trong số các cạnh kề của đỉnh s, cạnh (s, y) có độ dài nhỏ nhất. Tiếp theo, trong số các cạnh kề với 2 đỉnh s hoặc y ta tìm cạnh có độ dài nhỏ nhất, cạnh này dẫn đến đỉnh thứ ba z, và ta thu được cây bộ phận gồm 3 đỉnh và 2 cạnh. Quá trình này sẽ được tiếp tục cho tới khi ta thu được được cây gồm n đỉnh và n - 1 cạnh, cây đó cũng là cây bao trùm nhỏ nhất cần tìm. Các bước thuật toán như sau:
- Bước 1: Chọn u1 sao cho l(u1) = min{l(u)} với u ẻ U đặt U1 = {u1}
- Bước 2: Chọn u2 sao cho l(u2) = min{l(u)} với u ẻ U\U1 và u kề với 1 cạnh thuộc U1
...
- Bước k +1: Giả sử đã có Uk = {u1, u2, ..., uk}
Chọn uk + 1 sao cho l(uk+1) = min{l(u)} với u ẻ U\Uk và u kề với 1 cạnh thuộc Uk.
Với thuật toán Prim, cạnh mới được chọn cũng phải không lập thành chu trình với các cạnh đã chọn ở các bước trước.
Thuật toán dừng ở bước n - 1.
Kết luận: cây T = <X, Un-1> là cây bao trùm ngắn nhất của G.
* Về hình thức thuật toán Prim phức tạp hơn thuật toán Kruskal nhưng về khối lượng tính toán sẽ giảm đi rất nhiều lần. Bởi vì thuật toán Prim chỉ cần xét các cạnh kề với các cạnh đã được chọn, còn trong thuật toán Kruskal phải xem xét tất cả các cạnh còn lại của đồ thị. Chính vì thế thuật toán Prim tỏ ra hiệu quả hơn, còn thuật toán Kruskal phải tính toán nhiều nên làm việc kém hiệu quả đối với những đồ thị có số cạnh lớn.
3.2.3 Chương trình thể hiện thuật toán.
Chương trình Pascal thể hiện thuật toán Kruskal tìm cây bao trùm nhỏ nhất
Uses crt; Type
Arrn = Array[1..50] of integer; Arrm = Array[1..5000] of Integer; Var n, m, MinL : Integer;
Dau, Cuoi, W: Arrm; DauT, CuoiT, Father: Arrn; Connect: Boolean; Procedure NhapDl; Var i: Integer; FName: String; f: Text; Begin
Write('Cho ten file du lieu: '); Readln(Fname); Assign(f, Fname); Reset(f);
Readln(f,n,m);
For i:=1 to m do Readln(f,dau[i],Cuoi[i],W[i]); Close(f);
End;
Procedure Indulieu; Var i: Integer; Begin
Writeln('So dinh: ',n,' So canh: ',m); Writeln('Dinh dau Dinh cuoi Do dai');
For i:=1 to m do Writeln(Dau[i]:4, Cuoi[i]:10, W[i]:12); End;
Procedure Heap(First, Last: Integer); Var j, k ,t1, t2, t3: Integer;
Begin j:= First;
While (j<=Trunc(last/2)) do Begin
If (2*j < Last) and (W[2*j + 1] < W[2*j]) then k:= 2*j + 1
Else k:= 2*j;
If W[k]<W[j] then Begin
t1:= Dau[j]; t2:=Cuoi[j]; t3:=W[j];
Dau[k]:=t1; Cuoi[k]:=t2; W[k]:=t3; j:=k; End Else j:=Last; End; End;
Function Find(i: Integer): Integer; Var Tro: Integer;
Begin Tro:=i;
While Father[Tro]>0 do Tro:=Father[Tro]; Find:= Tro;
End;
Procedure Union(i, j : Integer); Var x: Integer;
Begin
x:=Father[i] + Father[j];
If Father[i]>Father[j] then Begin Father[i]:=j; Father[j]:=x; End Else Begin Father[j]:=i; Father[i]:=x; End; End; Procedure Kruskal;
Var i,Last, u, v, r1, r2, Ncanh, Ndinh: Integer; Begin
{Khoi tao mang Father danh dau cay con va khoi tao Heap} For i:=1 to n do Father[i]:=-1;
For i:=Trunc(m/2) downto 1 do Heap(i,m); Last:=m; Ncanh:=0; Ndinh:=0;
MinL :=0; Connect := True;
While (Ndinh< n - 1) and (Ncanh<m) do Begin NCanh := NCanh + 1;
u:= Dau[1]; v:= Cuoi[1];
{Kiem tra u va v co thuoc cung mot cay con} r1:= Find(u);
r2:= Find(v);
If r1<>r2 then Begin
{ket nap canh (u,v) vao cay khung} Ndinh := Ndinh + 1; Union(r1,r2); DauT[Ndinh]:=u;
CuoiT[Ndinh]:=v; MinL := Minl + W[1]; End;
{To chuc lai Heap} Dau[1]:= Dau[Last]; Cuoi[1]:= Cuoi[Last]; W[1]:=W[Last]; Last := Last - 1; Heap(1,Last); End;
If Ndinh <> n - 1 then Connect:= False; End;
Procedure InKetQua; Var i: Integer;
Begin
Writeln('Do dai cua cay khung nho nhat: ',MinL); Writeln('Cac canh cua cay khung nho nhat: ');
For i:=1 to n - 1 do Writeln('(',DauT[i]:2,', ',CuoiT[i]:2,')'); End;
BEGIN
NhapDl; InDuLieu; KrusKal;
If Connect then InKetQua
END.
3.3 ứng dụng cho bài toán kết nối hệ thống mạng
Hình 2.3
Xét 1 ứng dụng của đồ thị trong bài toán nối mạng máy tính: Cần nối mạng 1 hệ thống mạng gồm nhiều máy tính, kết nối làm sao giữa 2 máy bất kỳ đều có 1 đường thông tin qua lại, cho biết chi phí kết nối giữa các máy hãy tìm cách kết nối sao có tổng chi phí là thấp nhất. Để giải bài toán này, có thể mô hình bằng đồ thị trong đó mỗi máy là 1 đỉnh, các cạnh của đồ thị là tất cả các khả năng có thể kết nối giữa các máy, trên mỗi cạnh là trọng số tương ứng với chi phí kết nối. Rõ ràng đây là bài toán tìm cây bao trùm ngắn nhất của đồ thị. Giả sử có 1 hệ thống mạng như hình 2.3, cây bao trùm nhỏ nhất có những cạnh được tô đậm.
4. Cây bao trùm lớn nhất
4.1 Định nghĩa: Cây bao trùm lớn nhất của 1 đồ thị liên thông có trọng số là cây bao trùm có trọng số lớn nhất. cây bao trùm có trọng số lớn nhất.
Định nghĩa này cũng tương tự như định nghĩa cây bao trùm nhỏ nhất chỉ 1 điểm khác là ta thay trọng số bé nhất bằng trọng số lớn nhất như sau:
l(g) = Max {l(g') / g' ẻ Ă}
4.2 Thuật toán tìm cây bao trùm lớn nhất
Vấn đề tìm cây bao trùm lớn nhất cũng có thể tiến hành tương tự như cho cây bao trùm nhỏ nhất. Có thể áp dụng thuật toán Kruskal hoặc thuật toán Prim để tìm cây bao trùm lớn nhất, chỉ có khác là ở mỗi bước của thuật toán cạnh mới
0 1 2 4 5 3 6 7 8 5 2 8 9 6 11 3 7 3 4 6 9
được chọn là cạnh có trọng số lớn nhất. Khi đó cạnh uk+1 được chọn sao cho
l(uk+1) = Max{l(u) : u ẻ U\Uk}.
Ví dụ có thể cải tiến thuật toán Prim để tìm cây bao trùm lớn nhất của đồ thị n đỉnh như sau:
- Bước 1: Chọn u1 sao cho l(u1) = max{l(u)} với u ẻ U đặt U1 = {u1}
- Bước 2: Chọn u2 sao cho l(u2) = max{l(u)} với u ẻ U\U1 và u kề với 1 cạnh thuộc U1
...
- Bước k +1: Giả sử đã có Uk = {u1, u2, ..., uk}
Chọn uk + 1 sao cho l(uk+1) = max{l(u)} với u ẻ U\Uk và u kề với 1 cạnh thuộc Uk và không lập thành chu trình với các cạnh ẻ Uk
Thuật toán dừng ở bước thứ n - 1 khi đó ta tìm được cây bao trùm lớn nhất.
Kết luận
Tin học là công cụ đắc lực, là lĩnh vực có nhiều ứng dụng phục vụ cho nhiều ngành khác nhau trong đời sống xã hội. Cho nên việc nghiên cứu các vấn đề ứng dụng cho tin học cũng là việc nghiên cứu các ứng dụng được giải quyết như thế nào trên máy tính. Có nhiều bài toán ứng dụng, nếu được mô hình tốt bằng đồ thị thì sẽ dễ dàng giải quyết được trên máy tính, vì cấu trúc và quá trình xử lý lữu trữ thông tin trên máy tính có tính chất rời rạc không liên tục mà bản chất của đồ thị cũng là rời rạc. Nằm trong toán rời rạc, đồ thị đóng vai trò quan trọng làm cơ sở toán cho tin học, vì vậy đề tài được thực hiện không chỉ đạt được các kết quả nghiên cứu về các ứng dụng mà còn làm sáng tỏ hơn cơ sở lý thuyết toán trong tin học.
Đề tài được hoàn thành, các kết quả đạt được trong việc nghiên cứu ứng dụng của lý thuyết đồ thị chủ yếu đó là các ứng dụng để giải các bài toán tối ưu, bài toán lập lịch, đặc biệt trong các vấn đề về cây, ở đây ta tìm thấy nhiều ứng dụng cho việc phân tích các giải thuật, tuy là cơ sở nhưng rất trọng tâm, sự mô hình hoá được các giải thuật bằng cây tạo được khả năng phân tích các thuật toán này được rõ nét hơn, nhờ những kết quả nghiên cứu được từ cây lại làm rõ hơn bản
chất của thuật toán, ví dụ như thuật toán mã hoá tiền tố Huffman, các thuật toán sắp xếp và tìm kiếm...
Nếu đi hết tất cả các vấn đề của Lý thuyết đồ thị thì đó là một khối lượng kiến thức rất khổng lồ, các vấn đề ứng dụng của đồ thị cũng rất nhiều, rất phong phú và đa dạng. Tuy nhiên do hạn chế về trình độ, thời gian không nhiều và nằm trong khuôn khổ của cuốn luận văn, nên những kết quả đạt được vẫn chưa đầy đủ và có thể có nhiều sai sót. Nhiều vấn đề ứng dụng còn nêu ra chung chung, mới dừng lại trên mô hình lý thuyết, chưa có những chứng minh bằng số liệu hay là chương trình cài đặt cụ thể, có nhiều vấn đề của đồ thị mà chưa nêu được thuật toán giải quyết và vẫn còn nhiều thuật toán chưa được cài đặt trên máy tính. Mặc dù vậy, các kết quả đạt được cũng đã phần nào góp phần làm sáng tỏ những tính chất cơ bản của đồ thị và các ứng dụng của nó.
ứng dụng của đồ thị là rất thực tiễn và quan trọng, việc nghiên cứu lý thuyết đồ thị và các ứng dụng của nó góp phần phát triển các kỹ thuật Tin học, đặc biệt trong khâu lập trình. Cần có những phương hướng nghiên cứu toàn diện hơn về đồ thị nhưng vẫn xoay quanh các vấn đề trọng tâm và những ứng dụng quan trọng và phổ biến của đồ thị, các vấn đề ứng dụng của đồ thị là rất rộng, nhưng vào mỗi ứng dụng lại cần nghiên cứu sâu hơn, đầy đủ hơn.
Tài liệu tham khảo
1. Đỗ Đức Giáo
* Toán rời rạc - NXB Đại Học Quốc gia Hà nội, 1999.
* Cơ sở toán trong lập trình - NXB Khoa học và Kỹ thuật, Hà Nội, 1998.
2. Nguyễn Đức Nghĩa - Nguyễn Tô Thành
Toán rời rạc - NXB Giáo Dục, 1999.
3. Kenneth H.Rosen
Discrete Mathematics And Its Applications.
Bản dịch tiếng Việt: Toán học rời rạc ứng dụng trong Tin học NXB Khoa Học và Kỹ Thuật, Hà Nội 1998.
Người dịch: Phạm Văn Thiều - Đặng Hữu Thịnh.
4. Nguyễn Cam - Chu Đức Khánh
Lý thuyết đồ thị - NXB Tp Hồ Chí Minh, 1999.
5. Hoàng Chúng
Đại cương về toán học hữu hạn - NXB Giáo dục, 1997.
6. Đỗ Xuân Lôi
Cấu trúc dữ liệu và giải thuật - NXB thống kê, 1999.
7. Nguyễn Thúc Hải
Mạng máy tính và các hệ thống mở - NXB Giáo dục, 1997.
8. Vũ Đức Thi
Các thuật toán nén dữ liệu.
Mục lục
Nội dung Trang
Lời nói đầu
...
1 Giới thiệu đề tài
...
2 Mục lục
...
5
Chương 1 Một số vấn đề cơ bản của đồ thị 9
I. Các định nghĩa đồ thị... 9
1. Định nghĩa đồ thị... 9
3. Đa đồ thị ... 10 4. Giả đồ thị... 10 II. Các loại đồ thị ... 11 1. Đồ thị vô hướng ... 11 2. Đồ thị có hướng ... 11 3. Đồ thị hỗn hợp ... 11
III. Một số khái niệm và tính chất cơ bản của đồ ... thị 11 1. Bậc đồ thị ... 11 1.1 Bậc đồ thị vô hướng ... 11 1.2 Bậc đồ thị có hướng ... 12 2. Đường đi và chu trình ... 13 2.1 Đường đi ... 13 2.2 Chu trình ... 13 3. Đồ thị liên thông ... 14 4. Đồ thị con và đồ thị bộ phận ... 15
IV. Các dạng biểu diễn của đồ thị ... 15
1.Biểu diễn hình học của đồ thị ... 15
2. Sự đẳng cấu ... 16 3. Một số đồ thị đặc biệt ... 17 3.1 Đồ thị đều ... 17 3.2 Đồ thị đầy đủ ... 17 3.3 Đồ thị bánh xe ... 17 3.4 Một vài ứng dụng của đồ thị đặc biệt ... 18 4. Biểu diễn đồ thị trên máy tính ... 19
4.1 Biểu diễn bằng ma trận kề ...
19 4.2 Danh sách cạnh (cung) ... 22
Chương 2 Số ổn định và tô màu đồ thị ... 24
I. Số ổn định trong, số ổn định ngoài, nhân đồ thị ... 24
1. Số ổn định trong ... 24
2. Số ổn định ngoài ... 24
3. Nhân đồ thị ... 24
4. Các thuật toán tìm các tập ổn định trong cực đại, ổn định ngoài cực tiểu. 25 4.1 Thuật toán tìm số ổn định trong ... 25
4.2 Thuật toán tìm số ổn định ngoài... 25
5. ứng dụng đồ thị trong lập trình chơi cờ Ca rô... 26
II. tô màu đồ thị ... 29
1. Sắc số đồ thị ... 29