Đề và bài giải ôn thi cao học vào Học viện công nghệ bưu chính viễn thông
Trang 1BÀI TẬP ÔN THI CAO HỌC - 2012
-*** PHẦN 2: LÝ THUYẾT ĐỒ THỊ -***
-*Vấn đề 1: Duyệt đồ thị (DFS & BFS)
-Bài 1:
a) Trình bày thuật toán duyệt theo chiều sâu trên đơn đồ thị vô hướng
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Hãy áp dụng thuật toán duyệt theo chiều sâu để tìm các thành phần liên thông và cho biết mỗi thành phần liên thông gồm những đỉnh nào
HD:
a)
#include<stdio.h>
const max=20;//so dinh toi da
int n;//so dinh cua do thi
int a[max][max];//ma tran ke
int tham[max];//mang de danh dau dinh tham roi
int stplt=0;//so thanh phan lien thong
char *src="d:/dfs.txt";//tap tin luu ma tran ke
void DocFile(){
int i,j ;
FILE *f= fopen(src,"r");//mo file do thi de doc
fscanf(f,"%d",&n);//doc so dinh la n
printf("%d",n);
for(i=1;i<=n;i++){//doc ma tran ke
printf("\n");
for(j=1;j<=n;j++){
fscanf(f,"%d",&a[i][j]);
printf("%2d",a[i][j]);
}
fclose(f);//dong file
}
void DFS1(int u){//ham tham mot thanh phan lien thong voi dxp la u
printf("%d ",u); //tham dinh u
tham[u]=1; //danh dau u tham roi
for (int v=1;v<=n;v++)//xet cac dinh v tu 1 den n
if (tham[v]==0&&a[u][v]==1)//neu v chua tham va v ke u
DFS1(v);//goi de qui de tham v }
Trang 2void DFS(){//ham tham tat ca cac thanh phan lien thong
for (int u=1;u<=n;u++) tham[u]=0;//ban dau tat ca cac dinh la chua tham
for (u=1;u<=n;u++)//lan luot xet tat ca cac dinh u
if (tham[u]==0){//neu dinh u chua tham
stplt++;
printf("\nTplt thu %d:",stplt);
DFS1(u);//goi DFS1(u) de tham 1 thanh phan lien thong chua dinh u
}
void main() {
DocFile();
DFS();
}
b) DFS() lần lượt gọi:
+ DFS1(1) và thăm các đỉnh: 1,4,2,5,9,8,10 => tplt1: 1,4,2,5,9,8,10
+ DFS1(3) và các đỉnh được thăm là: 3,6,7 => tplt2: 3,6,7
Bài 2:
a) Trình bày thuật toán duyệt theo chiều rộng trên đơn đồ thị vô hướng
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Hãy áp dụng thuật toán duyệt theo chiều rộng để tìm các thành phần liên thông và cho biết mỗi thành phần liên thông gồm những đỉnh nào
HD:
a)
#include<stdio.h>
const max=20;//so dinh toi da
int n;//so dinh cua do thi
int a[max][max];//ma tran ke
int tham[max];//mang de danh dau dinh tham roi
int stplt=0;//so thanh phan lien thong
char *src="d:/bfs.txt";//tap tin luu ma tran ke
void DocFile(){
int i,j ;
FILE *f= fopen(src,"r");//mo file do thi de doc
fscanf(f,"%d",&n);//doc so dinh la n
printf("%d",n);
for(i=1;i<=n;i++){//doc ma tran ke
printf("\n");
for(j=1;j<=n;j++){
fscanf(f,"%d",&a[i][j]);
Trang 3}
fclose(f);//dong file
}
void BFS1(int u){//ham tham mot thanh phan lien thong voi dxp la u
int queue[max];//hang doi chua cac dinh theo thu tu tham
int d,c;//bien dau, cuoi de quan ly hang doi
d=c=1; //ban dau hang doi rong
queue[c++]=u; tham[u]=1;//cat dxp u vao hang doi va danh dau u tham roi
while( d!=c){//trong khi hang doi con khac rong
int u=queue[d++]; printf("%d ",u);//lay mot dinh u trong hang doi va in ra for(int v=1;v<=n;v++){//lan luot xet tat ca cac dinh v
if (tham[v]==0&&a[u][v]==1){//neu v chua tham va v ke u
queue[c++]=v; tham[v]=1;//cat v vao hang doi va danh dau v tham roi }
} }
}
void BFS(){//ham tham tat ca cac thanh phan lien thong
for (int u=1;u<=n;u++) tham[u]=0;//ban dau tat ca cac dinh la chua tham
for (u=1;u<=n;u++){//lan luot xet tat ca cac dinh u
if (tham[u]==0){//neu dinh u chua tham
stplt++;
printf("\nTplt thu %d:",stplt);
BFS1(u);//tham 1 thanh phan lien thong chua dinh u
}
}
void main() {
DocFile();
BFS();
}
b) BFS() lần lượt gọi:
+ BFS1(1) và các đỉnh được thăm là: 1,4,9,10,2,5,8 => tplt1: 1,4,9,10,2,5,8
+ BFS1(3) và các đỉnh được thăm là: 3,6,7 => tplt2: 3,6,7
Ta có trạng thái hàng đợi như sau: (E là hàng đợi rỗng)
1
4 9 10
9 10 2 5
10 2 5 8
5 8 8 E 3
6 7
7
E
Trang 4Bài 3:
a/ Hãy trình bày thuật toán tìm các cạnh cần bổ sung ít nhất và tìm các cạnh cần loại bỏ nhiều nhất sao cho đồ thị vẫn liên thông
b/ Cho biết kết quả khi áp dụng thuật toán đối với đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
HD:
a/
+ Duyệt đồ thị theo DFS/BFS, cạnh (i,j) đã đi qua sẽ đánh dấu a[i][j]=a[j][i]=2
+ Nếu số tplt là k thì số cạnh bổ sung ít nhất là k-1 và cạnh cần bổ sung là cạnh nối một đỉnh thuộc một tplt với một đỉnh thuộc tplt khác
+ Các cạnh (i,j) có a[i][j]=1 là các cạnh dư thừa cần loại
b/ Kết quả:
Cac canh can bo sung: (1,3); (3,8)
Cac canh can loai: (2,5);(6,7);(9,10)
Bài 4:
Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Hãy trình bày các bước sử dụng thuật toán BFS để tìm đường đi có số cạnh ít nhất từ đỉnh 2 đến đỉnh 10 HD:Vẽ queue với đxp=2, khi thăm đỉnh 10 thì ngừng Dựa vào bảng Trước sẽ tìm được đường đi ngằn nhất từ
2 đến 10
2
1
10 E
Bảng trước Đường đi có số cạnh ít nhất từ đỉnh 2 đến đỉnh 10:
2->4->1 ->8-> 10
Trang 5Bài 5:
Cho đơn đồ thị có hướng 10 đỉnh, dạng ma trận kề như sau:
Hãy trình bày các bước sử dụng thuật toán DFS/BFS chứng tỏ đồ thị liên thông yếu nhưng không liên thông mạnh
HD:
+ Đồ thị có hướng liên thông gọi là liên thông mạnh
+ Đồ thị có hướng không liên thông nhưng khi bỏ hướng đi sẽ liên thông thì gọi là liên thông yếu
+ Chứng tỏ đồ thị có hướng không liên thông mạnh: tìm một đỉnh xp sao cho khi duyệt DFS/BFS không thăm được tất cả các đỉnh khác.Vd duyệt DFS/BFS với dxp=1 sẽ không thăm được 3 => từ 1 đến 3 không có đường đi=> kg lt mạnh
+ Chứng tỏ đồ thị có hướng liên thông yếu: xây dựng ma trận kề của đồ thị vô hướng tương ứng Duyệt
DFS/BFS với đỉnh xp bất kỳ, nếu thăm được tất cả các đỉnh => lt yếu
Bài 6:
Cho đơn đồ thị có hướng 10 đỉnh, dạng ma trận kề như sau:
Hãy trình bày các bước sử dụng thuật toán DFS/BFS để chứng tỏ đồ thị liên thông mạnh
HD:
Chứng tỏ đồ thị có hướng liên thông mạnh: lần lượt duyệt DFS/BFS với tất cả các đỉnh xp, nếu tất cả các lần duyệt đều thăm được tất cả các đỉnh khác thì liên thông mạnh
-* Vấn đề 2: Đồ thị Euler & Hamilton
1 Euler
Đường đi qua tất cả các cạnh, mỗi cạnh được đi qua đúng một lần được gọi là đường đi Euler Chu trình qua qua tất cả các cạnh, mỗi cạnh được đi qua đúng một lần được gọi là chu trình Euler Đồ thị được gọi là đồ thị
Trang 6Euler nếu nó có chu trình Euler, và gọi là đồ thị nửa Euler nếu nó có đường đi Euler Mọi đồ thị Euler luôn là nửa Euler, nhưng điều ngược lại không luôn đúng
2 Hamilton
Đường đi qua tất cả các đỉnh, mỗi đỉnh được đi qua đúng một lần được gọi là đường đi Hamilton Chu trình qua qua tất cả các đỉnh, mỗi đỉnh được đi qua đúng một lần (trừ đỉnh xp) được gọi là chu trình Hamilton Đồ thị được gọi là đồ thị Hamilton nếu nó có chu trình Hamilton, và gọi là đồ thị nửa Hamilton nếu nó có đường đi Hamilton Mọi đồ thị Hamilton luôn là nửa Hamilton, nhưng điều ngược lại không luôn đúng
-Bài 1:
a) Phát biểu điều kiện cần và đủ để một đồ thị vô hướng là đồ thị Euler
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ G là đồ thị Euler
HD:
a) Đồ thị vô hướng G là đồ thị Euler nếu và chỉ nếu G liên thông và mọi đỉnh của G có bậc là số chẵn
b) Để chứng tỏ G là đồ thị Euler, ta thực hiện hai bước:
+ Chứng tỏ G liên thông: sử dụng thuật toán DFS/BFS, duyệt G với đỉnh xp bất kỳ Nếu thăm được tất cả các đỉnh thì G liên thông, ngược lại không liên thông
+ Chứng tỏ tất cả các đỉnh của G đều có bậc là số chẵn
( Bậc của đỉnh i bằng tổng các phần tử của hàng i hoặc cột i trong ma trận kề)
Bài 2:
a) Phát biểu điều kiện cần và đủ để một đồ thị vô hướng là đồ thị nửa Euler
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ G là đồ thị nửa Euler
HD:
a) Đồ thị vô hướng G là đồ thị nửa Euler nếu và chỉ nếu G liên thông và G không có quá hai đỉnh bậc lẻ (số đỉnh bậc lẻ bằng 0 hoặc bằng 2)
b) Để chứng tỏ G là đồ thị nửa Euler, ta thực hiện hai bước:
+ Chứng tỏ G liên thông: sử dụng thuật toán DFS/BFS, duyệt G với đỉnh xp bất kỳ Nếu thăm được tất cả các đỉnh thì G liên thông, ngược lại không liên thông
Trang 7+ Chứng tỏ G có số đỉnh bậc lẻ bằng 0 hoặc bằng 2.
( Bậc của đỉnh i bằng tổng các phần tử của hàng i hoặc cột i trong ma trận kề)
Bài 3:
a) Giả sử đồ thị có chu trình Euler, trình bày thuật toán tìm chu trình Euler
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ đồ thị có chu trình Euler và trình bày mỗi bước thực hiện theo thuật toán ở câu a để tìm một chu trình Euler bắt đầu từ đỉnh 1
HD:
a) Thuật toán tìm chu trình Euler:
void EulerCycle(){
stack=φ ; CE=φ ;// CE la tap chua cac dinh theo thu tu cua chu trinh Euler
Chọn đỉnh xp bất kỳ cất vào stack
Trong khi stack còn khác rỗng{
Gọi x là phần tử ở đỉnh stack ; Nếu (x còn đỉnh kề){
Chọn một đỉnh y kề x, cất y vào stack;
Loại bỏ cạnh (x,y) khỏi đồ thị }
Ngược lại{ //x khong con dinh ke
Lấy x ra khỏi stack ; cất x vào CE }
}
in tập CE theo thứ tự ngược
}
b) Chứng tỏ đồ thị có chu trình Euler và trình bày mỗi bước thực hiện để tìm một chu trình Euler bắt đầu từ đỉnh 1
* Để chứng tỏ G là đồ thị Euler, ta thực hiện hai bước:
+ Chứng tỏ G liên thông: sử dụng thuật toán DFS/BFS, duyệt G với đỉnh xp bất kỳ Nếu thăm được tất
cả các đỉnh thì G liên thông, ngược lại không liên thông
+ Chứng tỏ tất cả các đỉnh của G đều có bậc là số chẵn
( Bậc của đỉnh i bằng tổng các phần tử của hàng i hoặc cột i trong ma trận kề)
* Trình bày các bước tìm chu trình Euler: vẽ stack (nên vẽ stack theo chiều ngang)
Stack:
1
1 2
1 2 3
1 2 3 4
Trang 81 2 3 4 2
1 2 3 4 2 6
1 2 3 4 2 6 5
1 2 3 4 2 6 5 1
1 2 3 4 2 6 5 1 8
1 2 3 4 2 6 5 1 8 5
1 2 3 4 2 6 5 1 8 5 7
1 2 3 4 2 6 5 1 8 5 7 8
1 2 3 4 2 6 5 1 8 5 7 8 10
1 2 3 4 2 6 5 1 8 5 7 8 10 1
1 2 3 4 2 6 5 1 8 5 7 8 10
1 2 3 4 2 6 5 1 8 5 7 8 10 5
1 2 3 4 2 6 5 1 8 5 7 8 10 5 9
1 2 3 4 2 6 5 1 8 5 7 8 10 5 9 7
1 2 3 4 2 6 5 1 8 5 7 8 10 5 9 7 10
1 2 3 4 2 6 5 1 8 5 7 8 10 5 9 7
1 2 3 4 2 6 5 1 8 5 7 8 10 5 9
1 2 3 4 2 6 5 1 8 5 7 8 10 5
1 2 3 4 2 6 5 1 8 5 7 8 10
1 2 3 4 2 6 5 1 8 5 7 8
1 2 3 4 2 6 5 1 8 5 7
1 2 3 4 2 6 5 1 8 5
1 2 3 4 2 6 5 1 8
1 2 3 4 2 6 5 1
1 2 3 4 2 6 5
1 2 3 4 2 6
1 2 3 4 2
1 2 3 4
1 2 3
1 2
1
CE:1 2 3 4 2 6 5 1 8 5 7 8 10 5 9 7 10 1
Bài 4:
a) Giả sử đồ thị có đường đi Euler, trình bày thuật toán tìm một đường đi Euler
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ đồ thị có đường đi Euler và trình bày mỗi bước thực hiện theo thuật toán ở câu a để tìm một đường đi Euler
HD:
Trang 9a) Thuật toán tìm đường đi Euler giống thuật toán tìm chu trình Euler nhưng phải xuất phát từ đỉnh bậc lẻ b) vẽ stack để trình bày thuật toán (nên vẽ stack theo chiều ngang) và xuất phát từ đỉnh bậc lẻ
Bài 5:
Cho đa đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ đồ thị có chu trình Euler và trình bày mỗi bước thực hiện theo thuật toán để tìm một chu trình Euler bắt đầu từ đỉnh 6
HD: A[1][2]=4 nghĩa là có 4 cạnh (1,2)
Bài 6:
Cho đa đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ đồ thị có đường đi Euler và trình bày mỗi bước thực hiện theo thuật toán để tìm một đường đi Euler
Bài 7:
a) Phát biểu điều kiện cần và đủ để một đồ thị có hướng là đồ thị Euler
b) Cho đơn đồ thị có hướng 10 đỉnh, dạng ma trận kề như sau:
Trang 10Chứng tỏ đồ thị có chu trình Euler và trình bày mỗi bước thực hiện theo thuật toán ở câu b để tìm một chu trình Euler bắt đầu từ đỉnh 2
HD:
a) Đồ thị có hướng G là đồ thị Euler nếu và chỉ nếu G liên thông yếu và mọi đỉnh của G có bán bậc vào bằng bán bậc ra.
Bài 8:
a) Phát biểu điều kiện cần và đủ để một đồ thị có hướng là đồ thị nửa Euler
b) Cho đơn đồ thị có hướng 10 đỉnh, dạng ma trận kề như sau:
Chứng tỏ đồ thị có đường đi Euler và trình bày mỗi bước thực hiện theo thuật toán để tìm một đường đi Euler HD:
a) Đồ thị có hướng G là đồ thị nửa Euler nếu và chỉ nếu G liên thông yếu và G có đúng hai đỉnh u thỏa
|deg - (u)- deg + (u)|=1, mọi đỉnh khác của G có bậc vào bằng bậc ra Đỉnh xuất phát của đường đi Euler là một
trong hai đỉnh u nói trên với điều kiện deg+(u)>0 (bậc ra>0)
b) đỉnh 2 và đỉnh 8 có bậc vào và bậc ra chênh lệch 1=> đỉnh xuất phát là 2 hoặc 8
Bài 9:
a) Trình bày thuật toán tìm tất cả đường đi và chu trình Hamilton của 1 đồ thị với đỉnh xuất phát cho trước b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận kề như sau:
Vẽ cây lời giải để tìm tất cả đường đi và chu trình Hamilton bắt đầu từ đỉnh 1
HD:
a)
//chu trinh va duong di hamilton
#include<stdio.h>
const max=20;//so dinh toi da
int x[max];// luu cac dinh theo thu tu trên chu trình hamilton
int tham[max];//dung de danh dau dinh tham roi
int a[max][max];//ma tran ke
Trang 11int n;//so dinh cua do thi
int count=0;//so chu trinh
char *src="d:/hamilton.txt";
void DocFile(){
int i,j ;
FILE *f= fopen(src,"r");//mo file do thi de doc
fscanf(f,"%d",&n);//doc so dinh la n
for(i=1;i<=n;i++){//doc ma tran ke
for(j=1;j<=n;j++){
fscanf(f,"%d",&a[i][j]);
}
fclose(f);//dong file
}
void Try(int i){//tim dinh thu i trên chu trình hamilton
for(int j=1;j<=n;j++){//xet cac dinh j tu 1 den n
if(tham[j]==0&&a[x[i-1]][j]==1){//neu j chua tham va j ke voi x[i-1]
x[i]=j;//chon j lam dinh thu i trên chu trình tham[j]=1;//danh dau dinh j tham roi
if (i==n){//neu da tim du n dinh
if(a[x[n]][x[1]]==1){//neu dinh thu n ke voi dinh thu 1
printf("\n%d)CT:",++count);
for(int k=1;k<=n;k++){//in chu trình: x[1], ,x[n],x[1]
printf("%d ",x[k]);
} printf("%d",x[1]);
}else{//neu dinh thu n khong ke voi dinh thu 1
printf("\n%d)DD:",++count);
for(int k=1;k<=n;k++){//in duong di: x[1], ,x[n]
printf("%d ",x[k]);
} }
}else{
Try(i+1) ;//goi de qui de tim dinh thu i+1 }
tham[j]=0 ;//bo tham dinh j }
}
}
void Hamilton(int dxp){
for(int i=1;i<=n;i++) tham[i]=0;//ban dau tat ca cac dinh la chua tham
x[1]=dxp;//dxp la dinh thu nhat
tham[dxp]=1;//danh dau dxp tham roi
Try(2);//tim dinh thu 2
}
void main() {
int dxp;
DocFile();
printf("nhap dxp:");scanf("%d",&dxp);
Hamilton(dxp);
}
b) vẽ cây lời giải
Trang 12Bài 10:
Cho đơn đồ thị có hướng 10 đỉnh, dạng ma trận kề như sau:
Vẽ cây lời giải để tìm tất cả đường đi và chu trình Hamilton bắt đầu từ đỉnh 1
-* Vấn đề 3: Cây khung nhỏ nhất (Kruskal & Prim)
1 Cây: là đồ thị vô hướng, liên thông, không chu trình Cây có n đỉnh sẽ có n-1 cạnh
2 Cây khung của đồ thị: G=(V,E) là đồ thị vô hướng, liên thông Cây khung của đồ thị G là cây T=(V,F) với
F⊂E
3 Cây khung ngắn nhất của đồ thị: Là cây khung có tổng trọng số là nhỏ nhất
-Bài 1:
a) Trình bày thuật toán Kruskal tìm cây khung nhỏ nhất trên đồ thị vô hướng, liên thông có trọng số
b) Cho đơn đồ thị vô hướng 10 đỉnh, dạng ma trận trọng số như sau:
Trình bày kết quả tại mỗi bước khi áp dụng thuật toán Kruskal để tìm cây khung nhỏ nhất
HD:
a) Thuật toán Kruskal
void Kruskal(){
Sắp xếp danh sách các cạnh của đồ thị theo thứ tự tăng của trọng số
T=φ;// T là các tập cạnh của cây khung nhỏ nhất
lần lượt chọn (n-1) cạnh tren ds canh tu trai qua phai{
nếu (T∪{e} không chứa chu trình) thì thêm e vào T
ngược lại thì bỏ qua cạnh e, xét cạnh tiếp theo
}
in tập T
}
+ Thuật toán phát hiện chu trình:
- Ban đầu xem như có n cây con, mỗi cây có một đỉnh và đỉnh này là gốc của cây con
- Sử dụng mảng Trước để theo dõi gốc cây con chứa đỉnh i Đỉnh i có Trước[i]=-1 nghĩa là i là gốc của cây Ban đầu gán truoc[i]=-1 với mọi i