Đường đi và chu trình Euler

Một phần của tài liệu Giáo trình Kỹ thuật lập trình (Trang 116)

Chu trình đơn trong đồ thịGđi qua mỗi cạnh của đồ thịđúng một lần được gọi là chu trình Euler. Đường đi đơn trong G đi qua mỗi cạnh của nó đúng một lần được gọi là đường

đi Euler. Đồ thịđược gọi là đồ thị Euler nếu nó có chu trình Euler. Đồ thị có đường đi Euler

được gọi là nửa Euler.

Rõ ràng, mọi đồ thị Euler đều là nửa Euler nhưng điều ngược lại không đúng.

Ví dụ 1. Xét các đồ thị G1, G2, G3 trong hình 5.12. a b a b a b e e d c d c c d e G1 G2 G3 Hình 5.12. Đồ thị vô hướng G1, G2, G3.

Đồ thị G1 là đồ thị Euler vì nó có chu trình Euler a, e, c, d, e, b, a. Đồ thị G3 không có chu trình Euler nhưng chứa đường đi Euler a, c, d, e, b, d, a, b vì thế G3 là nửa Euler. G2 không có chu trình Euler cũng nhưđường đi Euler.

Định lý. Đồ thị vô hướng liên thông G=<V, E> là đồ thị Euler khi và chỉ khi mọi

đỉnh của Gđều có bậc chẵn. Đồ thị vô hướng liên thông G=<V, E> là đồ thị nửa Euler khi và chỉ khi nó không có quá hai đỉnh bậc lẻ.

Để tìm một chu trình Euler, ta thực hiện theo thuật toán sau:

ƒ Tạo một mảng CE để ghi đường đi và một stack để xếp các đỉnh ta sẽ xét. Xếp vào đó một đỉnh tuỳ ý u nào đó của đồ thị, nghĩa là đỉnh u sẽđược xét

đầu tiên.

ƒ Xét đỉnh trên cùng của ngăn xếp, giả sửđỉnh đó là đỉnh v; và thực hiện:

9 Nếu v là đỉnh cô lập thì lấy v khỏi ngăn xếp và đưa vào CE;

9 Nếu v là liên thông với đỉnh x thì xếp x vào ngăn xếp sau đó xoá bỏ cạnh (v, x);

ƒ Quay lại bước 2 cho tới khi ngăn xếp rỗng thì dừng. Kết quảđường đi Euler

được chứa trong CE theo thứ tự ngược lại.

Thủ tục Euler_Cycle sau sẽ cho phép ta tìm chu trình Euler.

void Euler_Cycle(int u){ Stack=φ; CE=φ;

u=>Stack; { nạp u vào stack}; while (Stack≠φ) {

x= top(Stack); { x là phần tửđầu stack } if (ke(x) ≠φ) {

y = Đỉnh đầu trong danh sách ke(x); Stack<=y; { nạp y vào Stack}; Ke(x) = Ke(x) \{y};

Ke(y) = Ke(y)\{x}; {loại cạnh (x,y) khỏi đồ thị};

} else { x<= Stack; {lấy x ra khỏi stack}; CE <=x; { nạp x vào CE;} } }

Ví dụ. Tìm chu trình Euler trong hình 5.13.

a b

4

1 2 3 5 6 7

f 8 c 9 d 10 e

Các bước thực hiện theo thuật toán sẽ cho ta kết quả sau:

Bước Giá trị trong stack Giá trị trong CE Cạnh còn lại

1 F 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 2 f, a 2, 3, 4, 5, 6, 7, 8, 9, 10 3 f, a, c 3, 4, 5, 6, 7, 8, 9, 10 4 f,a,c,f 3, 4, 5, 6, 7, 9, 10 5 f, a, c f 3, 4, 5, 6, 7, 9, 10 6 f, a, c, b f 3, 4, 6, 7, 9, 10 7 f, a, c, b, d f 3, 4, 7, 9, 10 8 f, a, c, b, d,c f 3, 4, 7, 10 9 f, a, c, b, d f, c 3, 4, 7, 10 10 f, a, c, b, d, e f, c 3, 4, 7 11 f, a, c, b, d, e, b f, c 3, 4 12 f, a, c, b, d, e, b, a f, c 3 13 f, a, c, b, d, e, b, a, d f, c 14 f, a, c, b, d, e, b, a f, c, d 15 f, a, c, b, d, e, b f,c,d,a 16 f, a, c, b, d, e f,c,d,a,b 17 f, a, c, b, d f,c,d,a,b,e 18 f, a, c, b f,c,d,a,b,e,d 19 f, a, c f,c,d,a,b,e,d,b 20 f, a f,c,d,a,b,e,d,b,c 21 f f,c,d,a,b,e,d,b,c,a 22 f,c,d,a,b,e,d,b,c,a,f (adsbygoogle = window.adsbygoogle || []).push({});

Một đồ thị không có chu trình Euler nhưng vẫn có thể có đường đi Euler. Khi đó, đồ

thị có đúng hai đỉnh bậc lẻ, tức là tổng các số cạnh xuất phát từ một trong hai đỉnh đó là số

lẻ. Một đường đi Euler phải xuất phát từ một trong hai đỉnh đó và kết thúc ởđỉnh kia. Như

vậy, thuật toán tìm đường đi Euler chỉ khác với thuật toán tìm chu trình Euler ở chỗ ta phải xác định điểm xuất phát của đường đi.

Để tìm tất cả các đường đi Euler của một đồ thị n đỉnh, m cạnh, ta có thể dùng kỹ

thuật đệ qui như sau:

ƒBước 1. Tạo mảng b có độ dài m + 1 như một ngăn xếp chứa đường đi. Đặt b[0]=1, i=1 (xét đỉnh thứ nhất của đường đi);

ƒBước 2. Lần lượt cho b[i] các giá trị là đỉnh kề với b[i-1] mà cạnh (b[i-1],b[i])

không trùng với những cạnh đã dùng từ b[0] đến b[i-1]. Với mỗi giá trị của b[i], ta kiểm tra:

9 Nếu i<m thì tăng i lên 1đơn vị (xét đỉnh tiếp theo) và quay lại bước 2.

Một phần của tài liệu Giáo trình Kỹ thuật lập trình (Trang 116)