Tải bản đầy đủ (.pdf) (20 trang)

Bài giảng lý thuyết đồ thị - Chương 3 pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (324.22 KB, 20 trang )

Giáo án môn: Lý Thuyết Đồ Thị

Nguyễn Minh Đức - ĐHQG Hà Nội
24
Chng 3



CC THUT TON TèM KIM TRấN THN V NG DNG


Trong lý thuyt th, cú rt nhiu thut toỏn c xõy dng da trờn c s duyt qua tt c cỏc
nh ca th sao cho mi nh ch c duyt ỳng mt ln. Do vy, vic xõy dng cỏc thut toỏn
cho phộp duyt qua tt c cỏc nh ca th mt cỏch cú h thng l mt vn quan trng thu hỳt
s quan tõm nghiờn cu ca nhiu nh khoa hc. Cỏc thut toỏn nh vy c gi chung l thut
toỏn tỡm kim trờn th.
Trong chng ny chỳng ta s nghiờn cu hai thut toỏn tỡm kim c bn trờn th l Thut
toỏn tỡm kim theo chiu sõu (Depth First Search) v Thut toỏn tỡm kim theo chiu rng (Breadth
First Search) v mt vi ng dng ca hai thut toỏn ny.
n gin cho vic trỡnh by, chỳng ta s xột th vụ hng G = (V,E), |V| = n, |E| = m;
th cú hng s c suy ra mt cỏch tng t vi mt vi im c bit cn chỳ ý.
ỏnh giỏ hiu qu ca cỏc thut toỏn ny, chỳng ta ch chỳ trng n vic ỏnh giỏ phc
tp tớnh toỏn ca thut toỏn, tc s phộp toỏn m thut toỏn cn thc hin trờn mi b d liu vo
trong trng hp xu nht. phc tp tớnh toỏn ny c biu din bng mt hm s ca kớch
thc d liu u vo. C th õy kớch thc ca d liu vo s l s nh n v s cnh m ca
th. Khi ú phc tp tớnh toỏn ca thut toỏn s c biu din bng hm hai bin f(n,m) l s
phộp toỏn nhiu nht m thut toỏn cn phi thc hin i vi mi th n nh, m cnh.
so sỏnh tc tng ca hai hm nhn giỏ tr khụng õm
f(n) v g(n) chỳng ta s dng ký hiu
f(n) = O(g(n)). iu ny cú ngha tng ng vi vic tỡm c cỏc hng s dng C v N sao
cho:


NnnCgnf );()(
Trng hp m rng, nu
f(n
1
,n
2
, ,n
k
) v g(n
1
,n
2
, ,n
k
) l cỏc hm biu din, ta vit:
f(n
1
,n
2
, ,n
k
)=O(g(n
1
,n
2
, ,n
k
))

Tỡm c cỏc hng s dng C v N sao cho:

f(n
1
,n
2
, ,n
k
)

Cg(n
1
,n
2
, ,n
k
) vi
Nn

Nu phc tp tớnh toỏn ca thut toỏn l
O(g(n)) thỡ ta núi l thut toỏn cú thi gian tớnh toỏn
c
O(g(n)).
3.1 Thut toỏn tỡm kim theo chiu sõu trờn th (Depth First Search)
í tng chớnh ca thut toỏn tỡm kim theo chiu sõu cú th c hiu nh sau:
Ban u tt c cỏc nh ca th u cha c duyt n, ta s bt u vic tỡm kim t mt nh
no ú, gi s nh ú l v
1
. Sau ú chn u l mt nh (cú th chn tu ý) trong danh sỏch cỏc nh
k vi nh v
1
m cha c xột n v lp li quỏ trỡnh tỡm kim i vi nh u ny. bc tng

quỏt, gi s ang xột nh v
k
, nu trong cỏc nh k vi nh v
k
ta tỡm c nh w l nh cha
c duyt n thỡ ta s li bt u quỏ trỡnh tỡm kim t ú v w s tr thnh nh ó c duyt
qua. Nu khụng cũn nh no k vi nh v
k
l cha c duyt n thỡ ta núi rng nh ny ó c
duyt xong v quay li tip tc tỡm kim t nh m trc ú ta n c nh v
k
. Quỏ trỡnh c tip
tc nh vy cho n khi tt c cỏc nh ca th ó c duyt ht. Nh vy ta cú th hiu mt
cỏch n gin l vic tỡm kim theo chiu sõu trờn th bt u t nh v c thc hin trờn c s
tỡm kim theo chiu sõu t cỏc nh cha c duyt k vi v.
Quỏ trỡnh ny c mụ t bng th tc quy sau:


Procedure DFS(v)
Giáo án môn: Lý Thuyết Đồ Thị

Nguyễn Minh Đức - ĐHQG Hà Nội
25
1
4
5
2
3
7
8

6
10
9
(* Tỡm kim theo chiu sõu trờn th bt u t nh v *)
(* Cỏc bin Chuaxet v Ke l bin ton cuc *)

Begin
Xet_dinh(v);
Chuaxet[v]:=False;
For u

Ke(v) do
If Chuaxet[u] Then
DFS(u);

End;
(* Chng trỡnh chớnh thc hin th tc *)

BEGIN
(* Khi to bin ton cc Chuaxet *)
For v
V do
Chuaxet[v]:=True;
(* Duyt th *)
For v
V do
If Chuaxet[v] Then
DFS(v);

END.

Nh vy, vi thut toỏn trờn õy rừ rng mi lnh gi DFS(v) s thc hin duyt qua tt c cỏc
nh cựng thnh phn liờn thụng vi nh v, bi vỡ sau mi khi xột nh v l lnh gi n th tc
DFS i vi cỏc nh k vi v. Mt khỏc, do mi khi thm nh v xong, bin Chuaxet[v] c gỏn
giỏ tr False nờn mi nh s c thm ỳng mt ln. Thut toỏn ln lt s tin hnh tỡm kim t
cỏc nh cha c xột n, vỡ vy nú s duyt c qua tt c cỏc nh ca th. (K c th
khụng liờn thụng).
D phc tp tớnh toỏn ca thut toỏn c ỏnh giỏ nh sau:
Trc ht ta thõy rng s phộp toỏn cn thc hin trong hai chu trỡnh ca thut toỏn (Hai vũng
For chng trỡnh chinh) cú c l n. Cũn th tc DFS phi thc hin khụng quỏ m ln. Do ú tng
s phộp toỏn cn thc hin trong cỏc th tc ny cú c l n+m. Vy phc tp tớnh toỏn ca thut
toỏn l O(n+m).
Vớ d 1:
Xột th vụ hng cho bi hỡnh di õy (Hỡnh 3.1)









Gi s danh sỏch k ca th c lu nh sau:

1:
2 3 4
2:
1 3
3:
1 2 5 8

4:
1 9 10
Hỡnh 3.1
Gi¸o ¸n m«n: Lý ThuyÕt §å ThÞ

NguyÔn Minh §øc - §HQG Hµ Néi
26
1
4
3
2
5
6
7
8
9
5:
3 8
6:
7 8
7:
6 8
8:
3 5 6 7
9:
4 10
10:
4 9
Khi đó thứ tự các đỉnh được duyệt theo thuật toán trên bắt đầu từ đỉnh 1 là:


1 2 3 5 8 6 7 4 9 10


Thuật toán tìm kiếm theo chiều sâu trên đồ thị có hướng cũng được thực hiện tương tự, trong
trường hợp này thủ tục DFS(v) sẽ cho phép duyệt tất cả các đỉnh u của đồ thị mà từ v có đường đi
tói u. Độ phức tạp tính toán của thuật toán trong trường hợp này vẫn là O(n+m).
Ví dụ 2:
Xét đồ thị có hướng cho bởi hình dưới đây (Hình 3.2)











Giả sử danh sách các đỉnh kề của đồ thị được lưu như sau:

1:
3
2:
1 4
3:

4:
5
5:

7 8
6:
5
7:
2 9
8:
6
9:


Khi đó thứ tự các đỉnh được duyệt theo thuật toán tìm kiếm theo chiều sâu bắt đầu từ đỉnh 1 là:

1 3 2 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à v
1
. Khi duyệt đỉnh v
1
ta sẽ để ý tới tất cả các đỉnh v
11
, v
12
, , v
1k

Hình 3.2

Giáo án môn: Lý Thuyết Đồ Thị

Nguyễn Minh Đức - ĐHQG Hà Nội
27
k vi nh v
1
m cha c xột n ngay sau ú ln lt xột ti cỏc nh ny, khi duyt nh v
1i

(i=1,2, k) ta li ý ti tt c cỏc nh k vi nú m cha c xột n ri ln lt xột n cỏc
nh ú. Qua trỡnh s c nh vy cho n khi no tt c cỏc nh ca th u c xột ht. Ta cú
th hỡnh dung phng phỏp ny nh hỡnh nh ca vt du loang, t mt im trờn mt phng du s
loang sang ngay cỏc im lõn cn vi im ú.
Vi phng phỏp ny ta thy rng cỏc nh k vi mt nh ca th s c xp hng theo th
t c ln lt xột ti, do ú chỳng ta cú th dựng c ch hng i thc hin cụng vic ny.
Th tc mụ t phng phỏp ny nh sau

Procedure BFS(v)
(* tỡm kim theo chiu rng bt u t nh v *)
(* Cỏc bin Chuaxet, Ke l ton cc *)
Begin
Queue : =


Queue

v; (* Np v vo Queue *)
Chuaxet[v]:=False;
While Queue



do
Begin
p
Queue; (* Ly p ra khi Queue *)
Xet_dinh(p);
For u

Ke(p) do
If Chuaxet[u] then
Begin
Queue

u;
Chuaxet[u]:=False;
End;
End;
End;
(* Chng trỡnh chớnh thc hin th tc *)
BEGIN
(* Khi to bin ton cc Chuaxet *)
For v

V do
Chuaxet[v]:=True;
(* Duyt cỏc nh *)
For v

V do
If Chuaxet[v] then

BFS(v);
END.
Vi thut toỏn ny ta cng thy rng mi lnh gi BFS(v) s thc hin duyt qua cỏc nh cựng
thnh phn liờn thụng vi nh v. Th tc BFS s c thc hin ln lt vi cỏc nh cha c
duyt ca th, do ú nú s duyt ht tt c cỏc nh ca th. Mt khỏc, mi khi duyt xong nh
v, bin Chuaxet[v] cng c gỏn giỏ tr False nờn mi nh s c thm ỳng mt ln.
Lp lun tng t thut toỏn tỡm kim theo chiu sõu ta cng cú c phc tp tớnh toỏn ca
thut toỏn ny l O(n+m).
Vớ d 3
Xột th vụ hng cho vớ d 1 (hỡnh 3.1)
Khi ú th t cỏc nh c duyt theo thut toỏn tỡm kim theo chiu rng 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<conio.h>

#include<stdio.h>
#include<stdlib.h>

#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
Vy ng i tỡm theo thut toỏn tỡm kim theo chiu sõu t nh 1 n nh 8 s l:

86521

Nu ỏp dng tỡm ng i theo thut toỏn tỡm kim theo chiu rng bt 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
Vy ng i tỡm theo thut toỏn tỡm kim theo chiu sõu t nh 1 n nh 8 s l:

8521


Chỳ ý

Xột theo cỏch duyt cỏc nh ca th thỡ ta cú th suy ra c ng i tỡm c theo thut
toỏn tỡm kim theo chiu rng l ng i cú s cnh ớt nht.
3.3.2 Bi toỏn kim tra tớnh liờn thụng ca th
Bi toỏn
Hóy cho bit th gm bao nhiờu thnh phn liờn thụng v cỏc nh trong tng thnh phn liờn
thụng ca th
Do hai th tc DFS(u) v BFS(u) u cho phộp ta duyt qua tt c cỏc nh thuc cựng mt thnh
phn liờn thụng vi nh u. Do ú s thnh phn liờn thụng ca th chớnh bng s ln ta gi ti
th tc DFS (hoc BFS) khi thc hin vic duyt qua tt c cỏc nh ca th. Vy gii quyt
bi toỏn trờn ta cú th ỏp dng mt trong hai th tc DFS hoc BFS, trong ú ta cn phi cú mt
bin Sotplt dựng m s thnh phn liờn thụng (s ln gi th tc) v mt bin mng Thanhplt[]
ỏnh du cỏc nh thuc cựng mt thnh phn liờn thụng vi nhau (cú th dựng ngay mng
Chuaxet[]). Cỏc th tc DFS v BFS cú th c sa li nh sau:

Th tc DFS:
Procedure DFS(u)
(* Bin Sotplt v Thanhplt[] l ton cc *)
Begin
Chuaxet[u]:=False;
Thanhplt[u]:=Sotplt;
For v

Ke(u) do
If Chuaxet[v] then
DFS(v);
End;

Th tc BFS:
Procedure BFS(u)
(* Bien Sotplt v Thanhplt[] l ton cc *)

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<conio.h>
#include<stdio.h>
#include<stdlib.h>
#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 \n\n");
if(kt)
{
//Khoi toa bien chuaxet;
for(i=1;i<=n;i++)
chuaxet[i]=1;
dd_bfs();
}
else
printf("\n\nDo thi chua duoc nha vao!");
printf("\n\n\n\n ");
printf("\nGo mot phim bat ky de tro ve menu chon chuc nang!");
getch();
break;
case '5': //Kiem tra tinh lien thong cu do thi
clrscr();
tieu_de();
printf("\n\n5.Kiem tra tinh lien thong cua do thi");
printf("\n ");
if(kt)
kiemtra_lt();

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();
break;
case '6': //Ket thuc chuong trinh
printf("\n\nXin cam on ban da su dung chuong trinh!");
getch();
break;
}
}while(ch!='6');
}










×