Giáo án môn Lý thuyết đồ thị

Chứng minh

Điều kiện cần:

Một đồ thị liên thông có chu trình Euler thì mỗi bậc của nó đều có bậc chẵn.

Thật vậy, giả sử chu trình Euler của đồ thị bắt đầu từ đỉnh v1 và tiếp theo là cạnh liên luộc với

v1, tức là cạnh (v1,v2). Cạnh (v1,v2) góp 1 vào deg(v1). Mỗi lần chu trình đi qua một đỉnh vk của

đồ thị, nó tăng thêm 2 đơn vị cho deg(vk) vì chu trình đi vào một đỉnh bằng một cạnh liên thuộc với

đỉnh đó và đi ra bằng một cạnh liên thuộc khác, điều đó có nghĩa các đỉnh vk (k ≠ 1) đều có bậc là

một số chẵn. Cuối cùng chu trình kết thúc ở đỉnh mà nó xuất phát v1, vì vậy nó tăng thêm 1 vào

deg(v1). Do đó deg(v1) cũng phải là một số chẵn. Vậy ta kết luận nếu đồ thị liên thông có chu trình

Euler thì mỗi đỉnh của nó đều có bậc chẵn.

Điều kiện đủ:

Một đồ thị liên thông mà các đỉnh đều có bậc chẵn thì tồn tại chu trình Euler trong đồ thị đó.

Thật vậy, giả sử G là một đồ thị liên thông với các đỉnh đều có bậc là một số chẵn. Ta đi xây

dựng một chu trình đơn bắt đầu từ đỉnh v1 tuỳ ý của đồ thị G. Trước tiên ta chọn cạnh (v1, v2), sau

đó là (v2, v3),. càng chọn được nhiều càng tốt. Đến một lúc nào đó đi mà ta đang chọn phải kết thúc

tại v1 với cạnh (vk,v1) vì đồ thị là hữu hạn và các đỉnh đều có bậc là một số chẵn. Điều này là chắc

chắn xãy ra vì mỗi lần đường đi qua một đỉnh bậc chẵn nó chỉ đi vào bằng một cạnh nên ít nhất vẫn

còn một cạnh để đi ra. Ví dụ trong đồ thị G cho bởi hình 4.3 ta bắt đầu ở đỉnh a và chọn tiếp các

cạnh (a, b), (b, c), (c, h) và (h, a).

pdf63 trang | Chia sẻ: trungkhoi17 | Lượt xem: 565 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Giáo án môn Lý thuyết đồ thị, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
4 5 7 9 8 6 3.2 Thuật toán tìm kiếm theo chiều rộng trên đồ thị (Breadth First Search) Tư tưởng chính của phương pháp tìm kiếm theo chiều rộng trên đồ thị có thể được hiểu như sau: Ban đầu tất cả các đỉnh của đồ thị là chưa được xét đến, ta sẽ bắt đầu việc tìm kiếm từ một đỉnh nào đó của đồ thị, giả sử đỉnh đó là v1. Khi duyệt đỉnh v1 ta sẽ để ý tới tất cả các đỉnh v11, v12, .., v1k Hình 3.2 Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 27 kề với đỉnh v1 mà chưa được xét đến để ngay sau đó lần lượt xét tới các đỉnh này, khi duyệt đỉnh v1i (i=1,2,..k) ta lại để ý tới tất cả các đỉnh kề với nó mà chưa được xét đến để rồi lần lượt xét đến các đỉnh đó. Qua trình sẽ cứ như vậy cho đến khi nào tất cả các đỉnh của đồ thị đều được xét hết. Ta có thể hình dung phương pháp này như hình ảnh của vết dầu loang, từ một điểm trên mặt phẳng dầu sẽ loang sang ngay các điểm lân cận với điểm đó. Với phương pháp này ta thấy rằng các đỉnh kề với một đỉnh của đồ thị sẽ được xếp hàng theo thứ tự để được lần lượt xét tới, do đó chúng ta có thể dùng cơ chế hàng đợi để thực hiện công việc này. Thủ tục mô tả phương pháp này như sau Procedure BFS(v) (* tìm kiếm theo chiều rộng bắt đầu từ đỉnh v *) (* Các biến Chuaxet, Ke là toàn cục *) Begin Queue : = φ Queue ⇐ v; (* Nạp v vào Queue *) Chuaxet[v]:=False; While Queue φ≠ do Begin p ⇐ Queue; (* Lấy p ra khỏi Queue *) Xet_dinh(p); For u ∈Ke(p) do If Chuaxet[u] then Begin Queue ⇐ u; Chuaxet[u]:=False; End; End; End; (* Chương trình chính thực hiện thủ tục *) BEGIN (* Khởi tạo biến toàn cục Chuaxet *) For v ∈ V do Chuaxet[v]:=True; (* Duyệt các đỉnh *) For v ∈ V do If Chuaxet[v] then BFS(v); END. Với thuật toán này ta cũng thấy rằng mỗi lệnh gọi BFS(v) sẽ thực hiện duyệt qua các đỉnh cùng thành phần liên thông với đỉnh v. Thủ tục BFS sẽ được thực hiện lần lượt với các đỉnh chưa được duyệt của đồ thị, do đó nó sẽ duyệt hết tất cả các đỉnh của đồ thị. Mặt khác, mỗi khi duyệt xong đỉnh v, biến Chuaxet[v] cũng được gán giá trị False nên mỗi đỉnh sẽ được thăm đúng một lần. Lập luận tương tự thuật toán tìm kiếm theo chiều sâu ta cũng có được độ phức tạp tính toán của thuật toán này là O(n+m). Ví dụ 3 Xét đồ thị vô hướng cho ở ví dụ 1 (hình 3.1) Khi đó thứ tự các đỉnh được duyệt theo thuật toán tìm kiếm theo chiều rộng sẽ là: 1 2 3 4 5 8 9 10 6 7 Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 28 Ví dụ 4 Xét đồ thị có hướng cho ở ví dụ 2 (Hình 2) Khi đó thứ tự các đỉnh được duyệt theo thuật toán tìm kiếm theo chiều rộng sẽ là: 1 3 2 4 5 7 8 9 6 Dưới đây là chương trình cài đặt hai thuật toán tìm kiếm theo chiều sâu và tìm kiếm theo chiều rộng bằng ngôn ngữ lập trình C. Chương trình xử lý trên đồ thị được cho bởi danh sách kề. //---------------------------------------------------------------------------- // huong trinh cai dat cac thuat toan tim kiem tren do thi // Depth First Search - Breadth First Search //---------------------------------------------------------------------------- #include #include #include #define VMAX 100 //So dinh toi da cho mot do thi typedef struct pp //Cau truc tu tro { int v; struct pp *next; }Link; Link *Ke[VMAX]; //Danh sach ke cua do thi int chuaxet[VMAX]; //Bien mang dung de danh dau cac dinh da xet Link *Queue; //Hang doi luu thu tu cac dinh se xet int n; //So dinh cua do thi //-------------------------------------------------------------------------- // Ham nhap danh sach ke cua do thi co n dinh //-------------------------------------------------------------------------- void nhap_dsk(Link *Ke[], int n) { int i,v; Link *pd,*p; //Khoi tao mang cac danh sach cac dinh ke cua cac dinh for(i=1;i<=n;i++) { Ke[i] = (Link*)malloc(sizeof(Link)); Ke[i]->v=i; Ke[i]->next = NULL; } //Nhap danh sach cac dinh ke cua cac dinh for(i=1;i<=n;i++) { pd = NULL; printf("\nNhap cac dinh ke voi dinh %d (nhap 0 de ket thuc!):",i); while(1) { Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 29 scanf("%d",&v); if(v==0) break; if(pd == NULL) { pd = (Link*)malloc(sizeof(Link)); p=pd; } else { p->next = (Link*)malloc(sizeof(Link)); p=p->next; } p->v=v; p->next = NULL; } Ke[i]->next = pd; } } //-------------------------------------------------------------------------- // Ham hien thi danh sach ke cua do thi co n dinh //-------------------------------------------------------------------------- void in_dsk(Link *Ke[], int n) { int i; Link *pd; printf("\nDanh sach ke cua cac dinh cua do thi:\n"); printf("\n ------------------\n"); for(i=1;i<=n;i++) { printf("\n Danh sach cac dinh ke cua dinh %d:",Ke[i]->v); pd = Ke[i]->next; while(pd!=NULL) { printf("%5d",pd->v); pd=pd->next; } } } //-------------------------------------------------------------------------- // Ham nap mot phan tu (mot dinh ) vao hang doi //-------------------------------------------------------------------------- void Push(Link *u) { Link *q,*p; q=(Link*)malloc(sizeof(Link)); q->v=u->v; q->next=NULL; if(Queue==NULL) Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 30 Queue = q; else { p=Queue; while(p->next!=NULL) p=p->next; p->next = q; } } //-------------------------------------------------------------------------- // Ham lay mot phan tu trong hang doi ra //-------------------------------------------------------------------------- int Pop() { if(Queue==NULL) return 0; //Quee rong! Link *p; p=Queue; Queue=p->next; int t=p->v; free(p); //Giai phong p return t; } //-------------------------------------------------------------------------- // Ham de quy tim kiem theo chieu sau bat dau tu mot dinh //-------------------------------------------------------------------------- void dfs(Link *u) { printf("%3d",u->v); chuaxet[u->v]=0; Link *p = Ke[u->v]->next; while(p!=NULL) { if(chuaxet[p->v]) dfs(p); p=p->next; } } //-------------------------------------------------------------------------- // Ham tim kiem theo chieu rong bat dau tu mot dinh //-------------------------------------------------------------------------- void bfs(Link *u) { Queue=NULL; //Khoi tao hang doi Push(u); chuaxet[u->v]=0; while(Queue!=NULL) { int u; Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 31 u=Pop(); printf("%5d",u); Link *p=Ke[u]->next; while(p!=NULL) { if(chuaxet[p->v]) { Push(p); chuaxet[p->v]=0; } p=p->next; } } } //-------------------------------------------------------------------------- // Ham in tieu de cua chuong trinh //-------------------------------------------------------------------------- void tieu_de() { printf("\n CHUONG TRINH CAI DAT CAC THUAT TOAN TIM KIEM TREN DO THI"); printf("\n --------------***--------------\n\n"); } //-------------------------------------------------------------------------- // Ham hien thi Menu chon chuc nang cua chuong trinh //-------------------------------------------------------------------------- char menu() { printf("\n Menu chon chu nang"); printf("\n ---***---\n"); printf("\n\n 1. Nhap do thi cho boi danh sach ke"); printf("\n\n 2. Hien thi danh sach ke cua do thi"); printf("\n\n 3. Tim kiem theo chieu sau tren do thi"); printf("\n\n 4. Tim kiem theo chieu rong tren do thi"); printf("\n\n 5. Ket thuc chuong trinh"); printf("\n\n ----------------------------------------"); printf("\n\n Ban chon:"); char ch=getche(); return ch; } //-------------------------------------------------------------------------- // Chuong trinh chinh //-------------------------------------------------------------------------- void main() { int kt=0,i; char ch; do { clrscr(); tieu_de(); Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 32 ch = menu(); switch(ch) { case '1': //Nhap danh sach ke cua do thi clrscr(); tieu_de(); kt=1; printf("\n\n1.Nhap danh sach ke cua do thi"); printf("\n------------------------------\n\n"); printf("\n\nSo dinh cua do thi n ="); scanf("%d",&n); nhap_dsk(Ke,n); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); break; case '2': //Hien thi danh sach ke cua do thi clrscr(); tieu_de(); printf("\n\n2.In danh sach ke cua do thi"); printf("\n----------------------------\n\n"); if(kt) in_dsk(Ke,n); else printf("\nDo thi chua duoc nhap vao!"); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); break; case '3': //Tim kiem theo chieu sau tren do thi clrscr(); tieu_de(); printf("\n\n3.Tim kiem theo chieu sau tren do thi"); printf("\n-------------------------------------\n\n"); if(kt) { //Khoi toa bien chuaxet; for(i=1;i<=n;i++) chuaxet[i]=1; //Ket qua tim kiem theo chieu sau printf("\n\nThu tu cac dinh duoc xet theo chieu xau:\n\n"); for(i=1;i<=n;i++) if(chuaxet[i]) dfs(Ke[i]); } else printf("\nDo thi chua duoc nhap vao!"); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); break; Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 33 case '4': //Tim kiem theo chieu rong tren do thi clrscr(); tieu_de(); printf("\n\n4.Tim kiem theo chieu rong tren do thi"); printf("\n--------------------------------------"); if(kt) { //Khoi toa bien chuaxet; for(i=1;i<=n;i++) chuaxet[i]=1; //Ket qua tim kiem theo chieu rong printf("\n\nThu tu cac dinh duoc xet theo chieu rong:\n\n"); for(i=1;i<=n;i++) if(chuaxet[i]) bfs(Ke[i]); } else printf("\nDo thi chua duoc nhap vao!"); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); break; case '5': //Ket thuc chuong trinh printf("\n\nXin cam on ban da su dung chuong trinh!"); getch(); break; } }while(ch!='5'); } 3.3 Ứng dụng của thuật toán tìm kiếm trên đồ thị Trong mục này chúng ta sẽ thực hiện ứng dụng hai thuật toán tìm kiếm trên đồ thị đã trình bầy ở trên vào việc giải hai bài toán cơ bản trên đồ thị là bài toán tìm một đường đi nối hai đỉnh bất kỳ của đồ thị và bài toán kiểm tra tính liên thông của đồ thị (xác định số thành phần liên thông của đồ thị). 3.3.1 Bài toán tìm đường đi giữa hai đính bất kỳ của đồ thị Bài toán Giả sử u và v là hai đỉnh nào đó của đồ thị G = (V,E), Hãy tìm đường đi từ đỉnh u tới đỉnh v. Như chúng ta đã biết hai thủ tục DFS(u) và BFS(u) sẽ cho phép duyệt qua tất cả các đỉnh thuộc cùng một thành phần liên thông với đỉnh u. Vì vậy sau khi thực hiện xong thủ tục mà biến Chuaxet[v] vẫn bằng True (đỉnh v chưa được duyệt) thì có nghĩa là không có đường đi từ u tới v, ngược lại nếu Chuaxet[v] = False thì v thuộc cùng một thành phần liên thông với u, hay tồn tại một đường đi từ u tới v. Trong trường hợp này, để ghi lại đường đi từ u tưới v ta có thể dùng một biến mảng Truoc[v] để lưu lại các đỉnh đi qua trước đỉnh v trong đường đi từ u tới v. Khi đó hai thủ tục DFS(u) và BFS(u) được sửa lại như sau: Thủ tục đệ quy tìm kiếm theo chiều sâu áp dụng cho việc tìm đường đi: Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 34 1 2 3 4 5 7 6 8 Procedure DFS(u) Begin Chuaxet[u]:=False; For v ∈Ke(u) do If Chuaxet[v] then Begin Truoc[v]:= u; DFS(v); End; End; Thủ tục tìm kiếm theo chiều rộng áp dụng cho việc tìm đường đi: Procedure BFS(u) Begin Queue : = φ Queue ⇐ v; Chuaxet[u]:=False; While Queue φ≠ do Begin p ⇐ Queue; For v ∈Ke(p) do If Chuaxet[v] then Begin Queue ⇐ v; Chuaxet[v]:=False; Truoc[v]:=p; End; End; End; Theo cách trên, đường đi cần tìm sẽ là: utTruoctvTruoctv ←←=←=← ...][:][: 121 Ví dụ 5 Xét đồ thị cho bởi hình dưới đây (Hình 3.3) Nếu áp dụng tìm đường đi theo thuật toán tìm kiếm theo chiều sâu bắt đầu từ đỉnh 1 ta sẽ có: Hình 3.3 Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 35 Truoc[2]=1, Truoc[3]=5, Truoc[4]=5, Truoc[5]=2, Truoc[6]=5, Truoc[7]=8, Truoc[8]=6 Vậy đường đi tìm theo thuật toán tìm kiếm theo chiều sâu từ đỉnh 1 đến đỉnh 8 sẽ là: 86521 ←←←← Nếu áp dụng tìm đường đi theo thuật toán tìm kiếm theo chiều rộng bắt đầu từ đỉnh 1 ta sẽ có: Truoc[2]=1, Truoc[3]=1, Truoc[4]=1, Truoc[5]=2, Truoc[6]=5, Truoc[7]=5, Truoc[8]=5 Vậy đường đi tìm theo thuật toán tìm kiếm theo chiều sâu từ đỉnh 1 đến đỉnh 8 sẽ là: 8521 ←←← Chú ý Xét theo cách duyệt các đỉnh của đồ thị thì ta có thể suy ra được đường đi tìm được theo thuật toán tìm kiếm theo chiều rộng là đường đi có số cạnh ít nhất. 3.3.2 Bài toán kiểm tra tính liên thông của đồ thị Bài toán Hãy cho biết đồ thị gồm bao nhiêu thành phần liên thông và các đỉnh trong từng thành phần liên thông của đồ thị Do hai thủ tục DFS(u) và BFS(u) đều cho phép ta duyệt qua tất cả các đỉnh thuộc cùng một thành phần liên thông với đỉnh u. Do đó số thành phần liên thông của đồ thị chính bằng số lần ta gọi tới thủ tục DFS (hoặc BFS) khi thực hiện việc duyệt qua tất cả các đỉnh của đồ thị. Vậy để giải quyết bài toán trên ta có thể áp dụng một trong hai thủ tục DFS hoặc BFS, trong đó ta cần phải có một biến Sotplt dùng để đếm số thành phần liên thông (số lần gọi thủ tục) và một biến mảng Thanhplt[] đánh dấu các đỉnh thuộc cùng một thành phần liên thông với nhau (có thể dùng ngay mảng Chuaxet[]). Các thủ tục DFS và BFS có thể được sửa lại như sau: Thủ tục DFS: Procedure DFS(u) (* Biến Sotplt và Thanhplt[] là toàn cục *) Begin Chuaxet[u]:=False; Thanhplt[u]:=Sotplt; For v ∈Ke(u) do If Chuaxet[v] then DFS(v); End; Thủ tục BFS: Procedure BFS(u) (* Bien Sotplt và Thanhplt[] là toàn cục *) Begin Queue : = φ Queue ⇐ v; Chuaxet[u]:=False; Thanhplt[u]:=Sotplt; While Queue φ≠ do Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 36 Begin p ⇐ Queue; For v ∈Ke(p) do If Chuaxet[v] then Begin Queue ⇐ v; Chuaxet[v]:=False; Thanhplt[v]:=Sotplt; End; End; End; Khi đó chương trình chính sẽ là: BEGIN Sotplt=0; For v ∈ V do Chuaxet[v]:=True; For v ∈ V do If Chuaxet[v] Then Begin Sotplt:=Sotplt+1; DFS(v); (* BFS(v) *) End; END. Dưới đây là chương trình được viết bằng ngôn ngữ C để giải quyết hai bài toán nói trên //-------------------------------------------------------------------------------------- // Chuong trinh cai dat ung dung cua thuat toan tim kiem tren do thi // ( Tim duong di va kiem tra tinh lien thong ) //-------------------------------------------------------------------------------------- #include #include #include #define VMAX 100 //So dinh toi da cho mot do thi typedef struct pp //Cau truc tu tro { int v; struct pp *next; }Link; Link *Ke[VMAX]; //Danh sach ke cua do thi int chuaxet[VMAX]; //Bien mang dung de danh dau cac dinh da xet Link *Queue; //Hang doi dung cho thuat toan tim kiem theo chieu rong int sTruoc[VMAX]; //Duong di tim theo thuat tim kiem theo chieu sau int rTruoc[VMAX]; //Duong di tim theo thuat tim kiem theo chieu rong int sotplt; //So thanh phan lien thong int n; //So dinh cua do thi //---------------------------------------------------------------------------------- // Ham nhap danh sach ke cua do thi co n dinh //---------------------------------------------------------------------------------- Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 37 void nhap_dsk(Link *Ke[], int n) { int i,v; Link *pd,*p; //Khoi tao mang cac danh sach cac dinh ke cua cac dinh for(i=1;i<=n;i++) { Ke[i] = (Link*)malloc(sizeof(Link)); Ke[i]->v=i; Ke[i]->next = NULL; } //Nhap danh sach cac dinh ke cua cac dinh for(i=1;i<=n;i++) { pd = NULL; printf("\nNhap cac dinh ke voi dinh %d (nhap 0 de ket thuc!):",i); while(1) { scanf("%d",&v); if(v==0) break; if(pd == NULL) { pd = (Link*)malloc(sizeof(Link)); p=pd; } else { p->next = (Link*)malloc(sizeof(Link)); p=p->next; } p->v=v; p->next = NULL; } Ke[i]->next = pd; } } //-------------------------------------------------------------------------- // Ham hien thi danh sach ke cua do thi co n dinh //-------------------------------------------------------------------------- void in_dsk(Link *Ke[], int n) { int i; Link *pd; printf("\nDanh sach ke cua cac dinh cua do thi:\n"); printf("\n ------------------"); for(i=1;i<=n;i++) { printf("\n Danh sach cac dinh ke cua dinh %d:",Ke[i]->v); Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 38 pd = Ke[i]->next; while(pd!=NULL) { printf("%5d",pd->v); pd=pd->next; } } } //-------------------------------------------------------------------------- // Ham nap mot phan tu (mot dinh ) vao hang doi //-------------------------------------------------------------------------- void Push(int t) { Link *q,*p; q=(Link*)malloc(sizeof(Link)); q->v=t; q->next=NULL; if(Queue==NULL) Queue = q; else { p=Queue; while(p->next!=NULL) p=p->next; p->next = q; } } //-------------------------------------------------------------------------- // Ham lay mot phan tu trong hang doi ra //-------------------------------------------------------------------------- int Pop() { if(Queue==NULL) return 0; //Quee rong! Link *p; p=Queue; Queue=p->next; int t=p->v; free(p); //Giai phong p return t; } //---------------------------------------------------------------------------------- // Ham de quy tim kiem theo chieu sau bat dau tu mot dinh // ( Ap dung de tim duong di giua hai dinh va kiem tra lien thong) //---------------------------------------------------------------------------------- void dfs(int u) { chuaxet[u]=sotplt; Link *p = Ke[u]->next; Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 39 while(p!=NULL) { if(chuaxet[p->v]==1) { sTruoc[p->v]=u; dfs(p->v); } p=p->next; } } //---------------------------------------------------------------------------------- // Ham tim kiem theo chieu rong bat dau tu mot dinh // ( Ap dung de tim duong di giua hai dinh va kiem tra lien thong) //---------------------------------------------------------------------------------- void bfs(int t) { Queue=NULL; //Khoi tao hang doi Push(t); chuaxet[t]=sotplt; while(Queue!=NULL) { int u; u=Pop(); Link *p=Ke[u]->next; while(p!=NULL) { if(chuaxet[p->v]==1) { Push(p->v); chuaxet[p->v]=sotplt; rTruoc[p->v]=u; } p=p->next; } } } //----------------------------------------------------------------------------- // Ham tim duong di giua hai dinh bat ky tren do thi // Ap dung thuat toan tim kiem theo chieu sau //----------------------------------------------------------------------------- void dd_dfs() { int dau, cuoi; printf("\n\nTim duong di tu dinh:"); scanf("%d",&dau); printf("den dinh:"); scanf("%d",&cuoi); dfs(dau); if(chuaxet[cuoi]==1) printf("\n\nKhong co duong di tu dinh %d den dinh %d tren do thi!",dau,cuoi); else Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 40 { printf("\n\nDuong di tu dinh %d den dinh %d tren do thi la:\n",dau,cuoi); printf("%d<--",cuoi); int j=cuoi; while(sTruoc[j]!=dau) { printf("%d<--",sTruoc[j]); j=sTruoc[j]; } printf("%d",dau); } } //------------------------------------------------------------------------------ // Ham tim duong di giua hai dinh bat ky tren do thi // Ap dung thuat toan tim kiem theo chieu rong //------------------------------------------------------------------------------ void dd_bfs() { int dau, cuoi; printf("\n\nTim duong di tu dinh:"); scanf("%d",&dau); printf("den dinh:"); scanf("%d",&cuoi); bfs(dau); if(chuaxet[cuoi]==1) printf("\n\nKhong co duong di tu dinh %d den dinh %d tren do thi!",dau,cuoi); else { printf("\n\nDuong di tu dinh %d den dinh %d tren do thi la:\n",dau,cuoi); printf("%d<--",cuoi); int j=cuoi; while(rTruoc[j]!=dau) { printf("%d<--",rTruoc[j]); j=rTruoc[j]; } printf("%d",dau); } } //-------------------------------------------------------------------------- // Ham kiem tra tinh lien thong cua do thi //-------------------------------------------------------------------------- void kiemtra_lt() { sotplt=1; for(int i=1;i<=n;i++) chuaxet[i]=1; for(i=1;i<=n;i++) if(chuaxet[i]==1) { Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 41 sotplt++; dfs(Ke[i]->v); //co the dung bfs(Ke[i]->v) thay cho dfs(Ke[i]->v) } if(sotplt==2) printf("\n\nDo thi la lien thong!"); else { printf("\n\nDo thi la khong lien thong!"); printf("\n\nSo thanh phan lien thong cua do thi la %d",sotplt-1); for(int j=2;j<=sotplt;j++) { printf("\n\nThanh phan lien thong thu %d gom cac dinh:",j); for(int k=1;k<=n;k++) if(chuaxet[k]==j) printf("%5d",k); } } } //-------------------------------------------------------------------------- // Ham in tieu de cua chuong trinh //-------------------------------------------------------------------------- void tieu_de() { printf("\n CHUONG TRINH TIM DUONG DI VA KIEM TRA TINH LIEN THONG"); printf("\n --------------***--------------\n\n"); } //-------------------------------------------------------------------------------- // Ham hien thi Menu chon chuc nang cua chuong trinh //-------------------------------------------------------------------------------- char menu() { printf("\n Menu chon chu nang"); printf("\n ---***---\n"); printf("\n\n 1. Nhap do thi cho boi danh sach ke"); printf("\n\n 2. Hien thi danh sach ke cua do thi"); printf("\n\n 3. Tim duong di - theo thuat tk chieu sau"); printf("\n\n 4. Tim duong di - theo thuat tk chieu rong"); printf("\n\n 5. Kiem tra tinh lien thong cua do thi"); printf("\n\n 6. Ket thuc chuong trinh"); printf("\n\n ----------------------------------------"); printf("\n\n Ban chon:"); char ch=getche(); return ch; } //-------------------------------------------------------------------------- // Chuong trinh chinh //-------------------------------------------------------------------------- void main() { int i,kt=0; Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 42 char ch; do { clrscr(); tieu_de(); ch = menu(); switch(ch) { case '1': //Nhap danh sach ke cua do thi clrscr(); tieu_de(); kt=1; printf("\n\n1.Nhap danh sach ke cua do thi"); printf("\n------------------------------\n\n"); printf("\n\nSo dinh cua do thi n ="); scanf("%d",&n); nhap_dsk(Ke,n); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); break; case '2': //Hien thi danh sach ke cua do thi clrscr(); tieu_de(); printf("\n\n2.In danh sach ke cua do thi"); printf("\n----------------------------\n\n"); if(kt) in_dsk(Ke,n); else printf("\n\nDo thi chu duoc nhap vao!"); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); break; case '3': //Tim duong di - theo thuat tk chieu sau clrscr(); tieu_de(); printf("\n\n3.Tim duong di - theo thuat tk chieu sau"); printf("\n-----------------------------------------\n\n"); if(kt) { //Khoi toa bien chuaxet; for(i=1;i<=n;i++) chuaxet[i]=1; dd_dfs(); } else printf("\n\nDo thi chua duoc nhap vao!"); printf("\n\n\n\n--------------------------------"); printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!"); getch(); Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ NguyÔn Minh §øc - §HQG Hµ Néi 43 break; case '4': //Tim duong di - theo thuat tk chieu rong clrscr(); tieu_de(); printf("\n\n4.Tim duong di - theo thuat tk chieu rong"); printf("\n---------

Các file đính kèm theo tài liệu này:

  • pdfgiao_an_mon_ly_thuyet_do_thi.pdf
Tài liệu liên quan