nh ngh a. 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 6.5. a b a b a b e e d c d c c d e G1 G2 G3 Hình 6.5. 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.
Ví d 2. Xét các đ th có h ng H1, H2, H3 trong hình 6.6. a b a b a b c c d e d d c H1 H2 H3 Hình 6.6. th có h ng H1, H2, H3.
th H2 là đ th Euler vì nó ch a chu trình Euler a, b, c, d, e, a vì v y nó là đ th Euler. th H3 không có chu trình Euler nh ng có đ ng đi Euler a, b, c, a, d, c nên nó là đ th n a Euler. th H1 không ch a chu trình Euler c ng nh chu trình 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:
̇ N u v là đnh cô l p thì l y v kh i ng n x p và đ a vào CE;
̇ 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. K t qu chu trình 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(void){ Stack:=φ; CE:=φ;
Ch n u là đnh nào đó c a đ th ; u=>Stack; /* n p u vào stack*/
while (Stack≠φ ) { /* duy t cho đ n khi stack r ng*/ 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 6.7.
a b
4
1 2 3 5 6 7
f 8 c 9 d 10 e
Hình 6.7. th vô h ng G.
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 Ch ng trình tìm chu trình Euler đ c th hi n nh sau:
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <math.h> #include <dos.h> #define MAX 50 #define TRUE 1 #define FALSE 0 int A[MAX][MAX], n, u=1; void Init(void){
int i, j;FILE *fp;
fp = fopen("CTEULER.IN", "r"); fscanf(fp,"%d", &n);
printf("\n So dinh do thi:%d",n); printf("\n Ma tran ke:");
for(i=1; i<=n;i++){ printf("\n"); for(j=1; j<=n;j++){ fscanf(fp,"%d", &A[i][j]); printf("%3d", A[i][j]); }
} fclose(fp); } int Kiemtra(void){ int i, j, s, d; d=0; for(i=1; i<=n;i++){ s=0; for(j=1; j<=n;j++) s+=A[i][j]; if(s%2) d++; } if(d>0) return(FALSE); return(TRUE); } void Tim(void){ int v, x, top, dCE;
int stack[MAX], CE[MAX]; top=1; stack[top]=u;dCE=0; do {
v = stack[top];x=1;
while (x<=n && A[v][x]==0) x++;
if (x>n) {
dCE++; CE[dCE]=v; top--;
} else { top++; stack[top]=x; A[v][x]=0; A[x][v]=0; } } while(top!=0);
for(x=dCE; x>0; x--) printf("%3d", CE[x]); } void main(void){ clrscr(); Init(); if(Kiemtra()) Tim();
else printf("\n Khong co chu trinh Euler"); getch();
}
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 đnh b c l này và k t thúc đnh b c l khác. Ch ng trình tìm đ ng đi Euler đ c th hi n nh sau: #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <math.h> #include <dos.h> #define MAX 50 #define TRUE 1 #define FALSE 0
void Init(int A[][MAX], int *n){ int i, j;FILE *fp;
fp = fopen("DDEULER.IN", "r"); fscanf(fp,"%d", n);
printf("\n So dinh do thi:%d",*n); printf("\n Ma tran ke:");
for(i=1; i<=*n;i++){ printf("\n");
fscanf(fp,"%d", &A[i][j]); printf("%3d", A[i][j]); } } fclose(fp); }
int Kiemtra(int A[][MAX], int n, int *u){ int i, j, s, d; d=0; for(i=1; i<=n;i++){ s=0; for(j=1; j<=n;j++) s+=A[i][j]; if(s%2){ d++;*u=i; } } if(d!=2) return(FALSE); return(TRUE); }
void DDEULER(int A[][MAX], int n, int u){ int v, x, top, dCE;
int stack[MAX], CE[MAX]; top=1; stack[top]=u;dCE=0; do {
v = stack[top];x=1;
while (x<=n && A[v][x]==0) x++;
if (x>n) {
dCE++; CE[dCE]=v; top--;
}
top++; stack[top]=x; A[v][x]=0; A[x][v]=0;
}
} while(top!=0);
printf("\n Co duong di Euler:"); for(x=dCE; x>0; x--) printf("%3d", CE[x]); } void main(void){ int A[MAX][MAX], n, u; clrscr(); Init(A, &n); if(Kiemtra(A,n,&u)) DDEULER(A,n,u);
else printf("\n Khong co duong di Euler"); getch(); } 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:
̇ 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.
̇ N u i==m thì dãy b chính là m t đ ng đi Euler.
Ch ng trình li t kê t t c đ ng đi Euler đ c th hi n nh sau:
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <math.h> #include <dos.h> #define MAX 50 #define TRUE 1
#define FALSE 0 int m, b[MAX], u, i, OK; void Init(int A[][MAX], int *n){
int i, j, s, d;FILE *fp;
fp = fopen("DDEULER.IN", "r"); fscanf(fp,"%d", n);
printf("\n So dinh do thi:%d",*n); printf("\n Ma tran ke:");
u=1; d=0; m=0; for(i=1; i<=*n;i++){ printf("\n");s=0; for(j=1; j<=*n;j++){ fscanf(fp,"%d", &A[i][j]); printf("%3d", A[i][j]); s+=A[i][j]; } if (s%2) { d++;u=i; } m=m+s; } m=m /2; if (d!=2) OK=FALSE; else OK=TRUE; fclose(fp); } void Result(void){ int i;
printf("\n Co duong di Euler:"); for(i=0; i<=m; i++)
printf("%3d", b[i]); }
void DDEULER(int *b, int A[][MAX], int n, int i){ int j, k;
for(j=1; j<=n;j++){
if (A[b[i-1]][j]==1){
A[b[i-1]][j]=0; A[j][b[i-1]]=0; b[i]=j;
if(i==m) Result(); else DDEULER(b, A, n, i+1);
A[b[i-1]][j]=1; A[j][b[i-1]]=1; } } } void main(void){ int A[MAX][MAX], n; clrscr(); Init(A, &n); b[0]=u;i=1;
if(OK) DDEULER(b, A, n, i);
else printf("\n Khong co duong di Euler"); getch();
}
6.6. NG I VÀ CHU TRÌNH HAMILTON
V i đ th Euler, chúng ta quan tâm t i vi c duy t các c nh c a đ th m i c nh đúng m t l n, thì trong m c này, chúng ta xét đ n m t bài toán t ng t nh ng ch khác nhau là ta ch quan tâm t i các đnh c a đ th , m i đnh đúng m t l n. S thay đ i này t ng nh không đáng k , nh ng th c t có nhi u s khác bi t trong khi gi i quy t bài toán.
nh ngh a. ng đi qua t t c các đnh c a đ th m i đnh đúng m t l n đ c g i là
đ ng đi Hamilton. Chu trình b t đ u t i m t đnh v nào đó qua t t c các đnh còn l i m i đnh
đúng m t l n sau đó quay tr l i v đ c g i là chu trình Hamilton. th đ c g i là đ th Hamilton n u nó ch a chu trình Hamilton. th ch a đ ng đi Hamilton đ c g i là đ th n a Hamilton.
Nh v y, m t đ th Hamilton bao gi c ng là đ th n a Hamilton nh ng đi u ng c l i không luôn luôn đúng. Ví d sau s minh h a cho nh n xét này.
Ví d . th đ thi hamilton G3, n a Hamilton G2 và G1.
a a b a b
b c c d c d
G1 G2 G3
Hình 6.8. th đ thi hamilton G3, n a Hamilton G2 và G1.
Cho đ n nay, vi c tìm ra m t tiêu chu n đ nh n bi t đ th Hamilton v n còn m , m c dù
đây là v n đ trung tâm c a lý thuy t đ th . H n th n a, cho đ n nay c ng v n ch a có thu t toán hi u qu đ ki m tra m t đ th có ph i là đ th Hamilton hay không.
li t kê t t c các chu trình Hamilton c a đ th , chúng ta có th s d ng thu t toán sau:
void Hamilton( int k) {
/* Li t kê các chu trình Hamilton c a đ th b ng cách phát tri n dãy đnh (X[1], X[2],..., X[k-1] ) c a đ th G = (V, E) */
for y∈ Ke(X[k-1]) {
if (k==n+1) and (y == v0) then Ghinhan(X[1], X[2],..., X[n], v0);
else {
X[k]=y; chuaxet[y] = false; Hamilton(k+1); chuaxet[y] = true; } } } Ch ng trình chính đ c th hi n nh sau: {
for (v∈V ) chuaxet[v] = true; /*thi t l p tr ng thái các đnh*/ X[1] = v0; (*v0 là m t đnh nào đó c a đ th *)
chuaxet[v0] = false; Hamilton(2);
Cây tìm ki m chu trình Hamilton th hi n thu t toán trên đ c mô t nh trong hình 6.9. 2 1 1 5 3 2 4 4 3 5 3 5 G=(V,E) 4 5 3 4 2 5 2 3 1 5 4 4 1 3 1 5 2 1 3 2 1 1 1 1
Hình 6.9. Cây tìm ki m chu trình Hamilton.
Ch ng trình li t kê các chu trình Hamilton đ c th hi n nh sau:
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <math.h> #include <dos.h> #define MAX 50 #define TRUE 1 #define FALSE 0
int A[MAX][MAX], C[MAX], B[MAX]; int n,i, d;
void Init(void){ int i, j;FILE *fp;
fp= fopen("CCHMTON.IN", "r"); if(fp==NULL){
printf("\n Khong co file input"); getch(); return;
}
fscanf(fp,"%d",&n);
printf("\n Ma tran ke:"); for(i=1; i<=n; i++){ printf("\n"); for(j=1; j<=n; j++){ fscanf(fp, "%d", &A[i][j]); printf("%3d", A[i][j]); } } fclose(fp); for (i=1; i<=n;i++) C[i]=0; }
void Result(void){ int i;
printf("\n "); for(i=n; i>=0; i--)
printf("%3d", B[i]); d++;
}
void Hamilton(int *B, int *C, int i){ int j, k;
for(j=1; j<=n; j++){
if(A[B[i-1]][j]==1 && C[j]==0){ B[i]=j; C[j]=1;
if(i<n) Hamilton(B, C, i+1);
else if(B[i]==B[0]) Result(); C[j]=0; } } } void main(void){ B[0]=1; i=1;d=0;
Init();
Hamilton(B,C,i); if(d==0)
printf("\n Khong co chu trinh Hamilton"); getch();
}
Ch ng trình duy t t t c đ ng đi Hamilton nh sau:
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <math.h> #include <dos.h> #define MAX 50 #define TRUE 1 #define FALSE 0
int A[MAX][MAX], C[MAX], B[MAX]; int n,i, d;
void Init(void){ int i, j;FILE *fp;
fp= fopen("DDHMTON.IN", "r"); if(fp==NULL){
printf("\n Khong co file input"); getch(); return;
}
fscanf(fp,"%d",&n);
printf("\n So dinh do thi:%d", n); printf("\n Ma tran ke:");
for(i=1; i<=n; i++){ printf("\n");
for(j=1; j<=n; j++){
fscanf(fp, "%d", &A[i][j]); printf("%3d", A[i][j]);
} }
fclose(fp); for (i=1; i<=n;i++) C[i]=0; }
void Result(void){ int i;
printf("\n "); for(i=n; i>0; i--)
printf("%3d", B[i]); d++;
}
void Hamilton(int *B, int *C, int i){ int j, k;
for(j=1; j<=n; j++){
if(A[B[i-1]][j]==1 && C[j]==0){ B[i]=j; C[j]=1;
if(i<n) Hamilton(B, C, i+1); else Result(); C[j]=0; } } } void main(void){ B[0]=1; i=1;d=0; Init(); Hamilton(B,C,i); if(d==0)
printf("\n Khong co duong di Hamilton"); getch();
NH NG N I DUNG C N GHI NH
X M t thu t toán tìm ki m trên đ th là phép vi ng th m các đnh c a nó m i đnh
đúng m t l n.
X Phép duy t theo chi u sâu s d ng c u trúc d li u stack.
X Phép duy t theo chi u r ng s d ng c u trúc d li u hàng đ i.
X Xác đnh các thành ph n liên thông và đ ng đi gi a hai đnh b t k c a đ th
đ u có th s d ng thu t toán DFS() ho c BFS().
X N m v ng và phân bi t rõ s khác bi t gi a chu trình (đ ng đi) Euler và chu trình (đ ng đi Hamilton).
X Ph ng pháp hi u rõ b n ch t nh t c a thu t toán là cài đ t và ki m ch ng thu t toán b ng cách vi t ch ng trình.
BÀI T P CH NG 6
Bài 1. Cho đ th G=<V, E> cho b i danh sách k . Hãy vi t th t c lo i b c nh (u,v) thêm c nh (x,y) vào đ th .
Bài 2. Áp d ng thu t toán tìm ki m theo chi u sâu đ tìm t t c các c u trên đ th vô h ng. (C u là c nh mà lo i b nó làm t ng s thành ph n liên thông c a đ th ).
Bài 3. Áp d ng thu t toán tìm ki m theo chi u sâu đ ki m tra xem đ th có h ng G=<V, A> có chu trình hay không.
Bài 4. Cho m t b ng ô vuông m x n ô, ô n m trên dòng i, c t j g i là ô (i, j): i=1,2,.., m; j=1, 2,..,n. Trong đó m i ô (i, j) ta vi t m t s a[i,j] ∈{0, 1}. Hãy vi t ch ng trình đ m s mi n con toàn 0 c a b ng. Ví d s mi n con toàn 0 c a b ng kích th c 5x5 đ c ch ra trong hình d i đây: 1 0 1 0 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 0 1 0 1 1 0
Bài 5. Vi t ch ng trình ki m tra xem m t đ th có là đ th Euler hay không? N u có câu kh ng đnh đúng hãy ch ra m t chu trình Euler trong đ th .
Bài 6. Vi t ch ng trình ki m tra xem m t đ th có là đ th n a Euler hay không? N u có câu kh ng đnh đúng hãy ch ra m t đ ng đi Euler trong đ th .
Bài 8. M t l p h c có 40 h c sinh v ngh hè. Bi t r ng m i em có đa ch ít nh t 20 b n, và n u b n này bi t đa ch c a b n kia thì b n kia c ng bi t đa ch c a b n này. Ch ng minh r ng b t c hai em nào trong l p c ng có th nh n tin cho nhau.
Bài 9. Ch ng minh r ng, đ i v i đ th liên thông G tùy ý có n c nh luôn luôn có th đánh s các c nh c a G b ng các s 1, 2,.., n, sao cho t i m i đnh mà đó có ít nh t 2 c nh c a đ th thì USCLN c a các s nguyên vi t trên các c nh thu c đnh này b ng 1.
Bài 10. Trên bàn c có 4x4 ô vuông. Ch ng minh r ng con mã không th đi qua t t c các ô, m i ô đúng m t l n r i tr v ô ban đ u.
CH姶愛NG VII: CÂY (TREE)
N i dung chính c a ch ng này đ c p đ n m t lo i đ th đ n gi n nh t đó là cây. Cây
đ c ng d ng r ng rãi trong nhi u l nh v c khác nhau c a tin h c nh t ch c các th m c, l u tr d li u, bi u di n tính toán, bi u di n quy t đnh và t ch c truy n tin. Nh ng n i dung đ c trình bày bao g m:
X Cây và các tính ch t c b n c a cây.
X M t s ng d ng quan tr ng c a cây trong tin h c.
X Cây khung c a đ th & các thu t toán c b n xây d ng cây khung c a đ th .
X Bài toán tìm cây khung nh nh t & các thu t toán tìm cây khung nh nh t.
X Thu t toán Kruskal tìm cây bao trùm nh nh t.
X Thu t toán Prim tìm cây bao trùm nh nh t.
B n đ c có th tìm th y nh ng ch ng minh c th cho các đnh lý, tính đúng đ n và đ
ph c t p các thu t toán thông qua các tài li u [1], [2].
7.1. CÂY VÀ M T S TÍNH CH T C B N
nh ngh a 1. Ta g i cây là đ th vô h ng liên thông không có chu trình. th không liên thông, không có chu trình đ c g i là r ng.
Nh v y, r ng là đ th mà m i thành ph n liên thông c a nó là m t cây.
Ví d . R ng g m 3 cây trong hình 7.1.
T1 T2 T3
Cây đ c coi là d ng đ th đ n gi n nh t c a đ th . nh lý sau đây cho ta m t s tính