Định nghĩa Rừng Forest: Rừng là đồ thị không có chu trìnhKhái niệm cây • Nhận xét: Rừng là đồ thị mà mỗi thành phần liên thông của nó là một cây... Các mệnh đề̀ sau tương đương:1 G là 1
Trang 1CHƯƠNG 6
Tôn Quang Toại
Khoa CNTT, Đại học Ngoại ngữ ‐ Tin học TP.HCM
Trang 4Định nghĩa Rừng (Forest): Rừng là đồ thị không có chu trình
Khái niệm cây
• Nhận xét: Rừng là đồ thị mà mỗi thành phần liên thông của nó là một cây.
C
Trang 5Định lý: Cho đồ̀ thị vô hướng G=(V, E) có n đỉnh. Các mệnh đề̀ sau tương đương:
(1) G là 1 cây (2) G không chứa chu trình và có n-1 cạnh (3) G liên thông và có n-1 cạnh
(4) G liên thông và mỗi cạnh của nó điều là cầu (5) Giữa hai đỉnh bất kỳ của G được nối với nhau bởi đúng một đường đi duy nhất
(6) G không chứa chu trình nhưng khi thêm vào một cạnh ta thu được đúng một chu trình
Các tính chất cơ bản của Cây
Trang 6Sơ đồ chứng minh:
Các tính chất cơ bản của Cây
Trang 7Chứng minh
Các tính chất cơ bản của Cây
Trang 8Chứng minh
Các tính chất cơ bản của Cây
Trang 9Chứng minh
Các tính chất cơ bản của Cây
Trang 10Chứng minh
Các tính chất cơ bản của Cây
Trang 11Chứng minh
Các tính chất cơ bản của Cây
Trang 12Định nghĩa Cây khung (spanning tree) của đồ̀ thị: Một cây T gọi là cây khung (cây bao trùm) của đồ thị G=(V, E) nếu
Trang 13n=4, số cây khung là: 4 16
Ví dụ: abc, bcd, cda, dab abf, acf, bdf,
e
a
b c
f d
n=5, Số cây khung là: 5 125
Trang 14Bài toán: Cho G là đồ thị vô hướng, liên thông, hãy tìm 1 cây khung của đồ thị
Lời giải
Thuật toán tìm kiếm theo chiều sâu (DFS)Thuật toán tìm kiếm theo chiều rộng (BFS)
Cây khung của đồ thị
Trang 15Tìm cây khung theo DFS
Cây khung của đồ thị
void SpanningTree_DFS(int u)
{
1 Đánh dấu u đã viếng thăm
2 Xét mọi đỉnh v chưa được viếng thăm và kề u, với từng đỉnh v đó
{
T = T {(u, v)}
DFS(v);
} }
Trang 16Tìm cây khung theo BFS
Cây khung của đồ thị
void SpanningTree_BFS()
{
<1 Khởi tạo>
- Đánh dấu mọi đỉnh chưa viếng thăm
- Đánh dấu u=0 đã viếng thăm
- q.Enqueue(u)
<2 Lặp>
while (q!=) {
}
}
Trang 17𝑤 𝑇 𝑤 𝑢, 𝑣
, ∈
Trang 18Thuật toán tìm cây khung nhỏ nhất
Có nhiều thuật toán xây dựng cây khung nhỏ nhất:
• Thuật toán Boruvka
• Thuật toán Kruskal
• Thuật toán Jarnik – Prim
Trang 19Thuật toán tìm cây khung nhỏ nhất
Thuật toán Kruskal:
Cây khung nhỏ nhất
Trang 20Input: G=(V, E) Output: Danh sách cạnh cay[]
Bước 1 (Sắp xếp) Sắp xếp các cạnh có trọng số tang dần
Bước 2 (Chọn n‐1 cạnh) Xét các cạnh theo thứ tự đã sắp xếp (cạnh nhỏ chọn trước) Chọn (n-1) cạnh theo quy tắc:
• Cạnh được chọn và cùng các cạnh đã chọn trước đó
không tạo thành chu trình
Cây khung nhỏ nhất
Trang 21Ví dụ: Dùng thuật toán Kruskal để m cây khung nhỏ nhất của đồ thị sau:
Cây khung nhỏ nhất
A
C B
8
1
9 3
Trang 23Vấn đề: Chúng ta phải cập nhật bảng connected[][] này như thế nào?
Lúc u và v chưa nối thì {x} và {y} chưa liên thông
Nếu nối u với v thì phải cập nhật các đỉnh {x} liên thông với các đỉnh {y}
Trang 24Bước 1 (Sắp xếp)Sắp xếp các cạnh theo thứ tự tăng dần về trọng số
Bước 2: Lặp (n‐1) lầnXét các cạnh theo thứ tự đã sắp xếp (cạnh nhỏ xét trước)
• [Tìm cạnh] : Tìm cạnh (u, v) không liên thông đưa vào T
• [Cập nhật] : Cập nhật 2 miền liên thông chứa đỉnh {u} và {v} tương ứng thành 1 miền
Cây khung nhỏ nhất
Trang 25void Kruskal() {
}
Trang 26Một số cách kiểm tra 2 đỉnh có liên thông hay không:
Dùng mảng 2 chiều: int connected[][];
connected[i][j] = true nếu i liên thông j (=0 ngược lại)
Dùng mảng 1 chiều: int connected[];
connected[i] = connected[j] thì i liên thông jDùng Union‐Find set
Cây khung nhỏ nhất
Trang 27• Đánh dấu y
Cây khung nhỏ nhất
Trang 28Bước 1: Chọn đỉnh x0 bất kỳ và và đưa vào cây (đánh dấu x0)
Bước 2: Lần lượt nạp (n-1) đỉnh còn lại (tương ứng n‐1 cạnh ) vào cây bằng cách:
• Chọn cạnh (x, y) thỏa điều kiện:
– x thuộc cây (x đã đánh dấu) – y chưa thuộc cây (y chưa đánh dấu) – Độ dài cạnh (x, y) nhỏ nhất
• Đánh dấu y
Cây khung nhỏ nhất
Trang 29Ví dụ: Dùng thuật toán Prim để m cây khung nhỏ nhất của đồ thị sau:
Cây khung nhỏ nhất
A
C B
8
1
9 3
Trang 30void Jarnik_Prim()
{
}
Trang 31Cây khung nhỏ nhất
Trang 32Tóm tắt chương 6