CuuDuongThanCong.com
Tìm kiếm trên đồ thị (Version 0.4)
Trần Vĩnh Đức
HUST
Ngày 29 tháng 7 năm 2018
/>
1 / 57
Tài liệu tham khảo
▶ S. Dasgupta, C. H. Papadimitriou, and U. V. Vazirani,
Algorithms, July 18, 2016.
▶ Chú ý: Nhiều hình vẽ trong tài liệu được lấy tùy tiện mà chưa
xin phép.
CuuDuongThanCong.com
/>
2 / 57
Nội dung
Biểu diễn đồ thị
Tìm kiếm theo chiều sâu trên đồ thị vơ hướng
Tìm kiếm theo chiều sâu trên đồ thị có hướng
Thành phần liên thơng mạnh
CuuDuongThanCong.com
/>
Biểu diễn đồ thị dùng Ma trận kề
Nếu đồ thị có n = |V| đỉnh v1 , v2 , . . . , vn , thì ma trận kề là một
mảng n × n với phần tử (i, j) của nó là
{
1 nếu có cạnh từ vi tới vj
aij =
0 ngược lại.
Ví dụ
CuuDuongThanCong.com
v2
1 1 1
A = 0 0 1
0 1 0
v1
v3
/>
4 / 57
Dùng ma trận kề có hiệu quả?
▶ Có thể kiểm tra có cạnh nối giữa cặp đỉnh bất kỳ chỉ cần một
lần truy cập bộ nhớ.
▶ Tuy nhiên, không gian lưu trữ là O(n2 )
CuuDuongThanCong.com
/>
5 / 57
Biểu diễn đồ thị dùng danh sách kề
▶ Dùng một mảng Adj gồm |V| danh sách.
▶ Với mỗi đỉnh u ∈ V, phần tử Adj[u] lưu trữ danh sách các
hàng xóm của u. Có nghĩa rằng:
Adj[u] = {v ∈ V | (u, v) ∈ E}.
Ví dụ
CuuDuongThanCong.com
1
Adj[0] = {0, 1, 2}
Adj[1] = {2}
Adj[2] = {1}
0
2
/>
6 / 57
Dùng danh sách kề có hiệu quả?
▶ Có thể liệt kê các đỉnh kề với một đỉnh cho trước một cách
hiệu quả.
▶ Nó cần khơng gian lưu trữ là O(|V| + |E|). Ít hơn O(|V|2 ) rất
nhiều khi đồ thị ít cạnh.
CuuDuongThanCong.com
/>
7 / 57
Nội dung
Biểu diễn đồ thị
Tìm kiếm theo chiều sâu trên đồ thị vơ hướng
Tìm kiếm theo chiều sâu trên đồ thị có hướng
Thành phần liên thơng mạnh
CuuDuongThanCong.com
/>
EALIZE THAT THE ORDER IN WHICH EDGES
WHICH VERTICES APPEAR IN THE ARRAY OF
H
M
T
E
R
E CâutinyG.txt
hỏi
đỉnh của đồ thị ta có
đi tớiGraph
những tinyG.txt
đỉnh nào?
% thể
java
T VTừ một
13
E
13 vertices, 13 edges
13
Y
0: 6 2 1 5
0 5
1: 0
T
4 3
2: 0
0 1
first adjacent
N
3: 5 4
CuuDuongThanCong.com
/>
9 / 57
Tìm đường trong mê cung
Algorithms
83
Figure 3.2 Exploring a graph is rather like navigating a maze.
L
K
D
G
H
A
B
C
F
F
E
I
J
J
K
H
B
E
C
G
L
I
A
D
Hình: Tìm kiếm trên đồ thị cũng giống tìm đường trong mê cung
3.2 Depth-first search in undirected graphs
3.2.1 Exploring mazes
Depth-first search is a surprisingly versatile linear-time procedure that reveals a
wealth of information about a graph. The most basic question it addresses is,
What
CuuDuongThanCong.com
parts of the graph
are reachable from a given vertex?
/>
10 / 57
procedure explore(G, v)
Input: đồ thị G = (V, E); v ∈ V
Output: visited(u)=true với mọi đỉnh u có thể đến
được từ v
visited(v) = true
previsit(v)
for each edge (v, u) ∈ E:
if not visited(u): explore(G, u)
postvisit(v)
CuuDuongThanCong.com
/>
11 / 57
Ví dụ: Kết quả chạy explore(G, A)
A
Chapter 3
Figure 3.2 Exploring
is rather
like navigating
a maze.
Figure 3.4a graph
The result
of explore(A)
on the graph
of Figure
L
K
D
A
B
A
F
E
B
B
G
H
C
F
I
J
F
E
J
K
L
I
J
C
I
E
D
G
C
H
A
For instance, while B was being visited, the edge B − E was n
3.2 Depth-first
in undirected
graphs
was as search
yet unknown,
was traversed via
a call to explore(E )
form a tree (a connected graph with no cycles) and are therefo
3.2.1 Exploring
mazesedges were ignored because they led back to familia
The dotted
CuuDuongThanCong.com
/>
12 / 57
Tìm kiếm theo chiều sâu
procedure dfs(G)
for all v ∈ V:
visited(v) = false
for all v ∈ V :
if not visited(v): explore(G, v)
CuuDuongThanCong.com
/>
13 / 57
during explore(x) and once during explore(y). The overall time for step 2 is
therefore O(|E |) and so the depth-first search has a running time of O(|V| + |E |),
linear in the size of its input. This is as efficient as we could possibly hope for, since
it takes this long even just to read the adjacency list.
Ví dụ: Đồ thị và Rừng DFS
Figure 3.6 (a) A 12-node graph. (b) DFS search forest.
(a)
(b)
A
B
C
1,10
11,22
23,24
A
C
F
D
B
E
4,9
12,21
D
I
5,8
13,20
H
2,3
E
F
G
H
I
J
K
L
J
14,17
G
6,7
L
18,19
K
15,16
Figure 3.6 shows the outcome of depth-first search on a 12-node graph, once again
breaking ties alphabetically (ignore the pairs of numbers for the time being). The
outer loop of DFS calls explore three times, on A, C , and finally F . As a result,
there are three trees, each rooted at one of these starting points. Together they
constitute a forest.
CuuDuongThanCong.com
/>
14 / 57
Bài tập
Xây dựng rừng DFS cho đồ thị sau với các đỉnh lấy theo thứ tự từ
điển. Vẽ cả những cạnh nét đứt.
CuuDuongThanCong.com
/>
15 / 57
Rừng
vàforest.
số thành
. (b)
DFSDFS
search
(b)
phần liên thông
1,10
11,22
23,24
A
C
F
B
E
4,9
12,21
D
I
5,8
13,20
H
2,3
J
14,17
G
6,7
L
18,19
K
15,16
v
A
B
C
D
E
F
G
H
I
J
ccnum[v]
1
1
2
2
1
3
2
2
1
1
Biến ccnum[v] để xác định thành phần liên thông của đỉnh v.
depth-first search on a 12-node graph, once again
re the pairs of numbers for the time being). The
CuuDuongThanCong.com
/>
16 / 57
Tính liên thơng trong đồ thị vơ hướng
procedure dfs(G)
cc = 0
for all v ∈ V: visited(v) = false
for all v ∈ V:
if not visited(v):
cc = cc + 1
explore(G, v)
procedure explore(G, v)
visited(v) = true
previsit(v)
for each edge (v, u) ∈ E:
if not visited(u): explore(G, u)
postvisit(v)
procedure previsit(v)
ccnum[v] = cc
CuuDuongThanCong.com
/>
17 / 57
Bài tập
Hãy cài đặt chương trình tìm số thành phần liên thông của một đồ
thị vô hướng.
CuuDuongThanCong.com
/>
18 / 57
previsit và postvisit
▶ Lưu thời gian lần đầu đến đỉnh trong mảng pre
▶ Lưu thời gian lần cuối rời khỏi đỉnh trong mảng post
▶ Để tính hai thơng tin này ta dùng một bộ đếm clock, khởi
tạo bằng 1, và được cập nhật như sau:
CuuDuongThanCong.com
procedure previsit(v)
pre[v] = clock
clock = clock + 1
procedure postvisit(v)
post[v] = clock
clock = clock + 1
/>
19 / 57
Bài tập
Vẽ rừng DFS với cả số pre và post cho mỗi đỉnh cho đồ thị sau.
CuuDuongThanCong.com
/>
20 / 57
Tính chất của previsit và postvisit
Mệnh đề
Với mọi đỉnh u và v, hai khoảng
[ pre(u), post(u) ] và [ pre(v), post(v) ]
▶ hoặc là rời nhau,
▶ hoặc là có một khoảng chứa một khoảng khác.
Tại sao? vì [ pre(u), post(u) ] là khoảng thời gian đỉnh u nằm
trong ngăn xếp. Cấu trúc vào-sau, ra-trước đảm bảo tính chất này.
CuuDuongThanCong.com
/>
21 / 57
Nội dung
Biểu diễn đồ thị
Tìm kiếm theo chiều sâu trên đồ thị vơ hướng
Tìm kiếm theo chiều sâu trên đồ thị có hướng
Thành phần liên thơng mạnh
CuuDuongThanCong.com
/>
Bài tập
88
Hãy vẽ rừng DFS với
số pre
post
trên mỗi
đỉnh cho đồ thị có
Figure
3.7 và
DFS
on a directed
graph.
hướng sau.
CuuDuongThanCong.com
A
B
A
C
B 2,11
E
F
D
G
H
E 3,10
4,7
F
5,6
G
H
In further analyzing the directed case, it helps to have terminolog
relationships between nodes of a tree. A is the root of the search
/>
23 / 57
88
3.3 Depth-first search in
Lời giải
Figure
3.7 DFS on a directed graph.
A 1,16
B
E
A
F
G
C
D
4,7
F
5,6
G
B 2,11
C 12,15
E 3,10
D 13,14
H
8,9
H
In further analyzing the directed case, it helps to have terminology for important
relationships between nodes of a tree. A is the root of the search tree; everything
else is its descendant. Similarly,
E has descendants F , G , and H , and conversely,
CuuDuongThanCong.com
/>
24 / 57
relationships between nodes of a tree. A is the root of the search tree; everything
else is its descendant. Similarly, E has descendants F , G , and H , and conversely,
is an ancestor of these three nodes. The family analogy is carried further: C is the
parent of D, which is its child.
Các kiểu cạnh
For undirected graphs we distinguished
between
treethuộc
edges and
nontree
Tree Edges
là cạnh
rừng
DFS.edges. In
the directed case, there is a slightly more elaborate taxonomy:
DFS tree
Forward
Edgespart
là ofcạnh
dẫnforest.
từ một
Tree edges
are actually
the DFS
A
war
Bac
k
For
Tr
ee
d
B
C
Cross
D
nút
tới một nút con cháu của nó nhưng
Forward edges lead from a node to a nonchild descendant in
không
the DFS
tree. thuộc rừng DFS.
Back edges lead to an ancestor in the DFS tree.
Cross edges lead to neither descendant nor ancestor; they
Back
là cạnh
dẫnalready
từ một
tới
therefore
leadEdges
to a node
that has
beennút
completely
explored
already
một(that
tổ is,
tiên
của postvisited).
nó.
Crosstwo
Edges
cạnhanddẫn
một
nútCan
tới you
Figure 3.7 has two forward edges,
back là
edges,
twotừ
cross
edges.
spot them?
một nút không phải tổ tiên cũng không
Ancestor and descendant relationships,
well as
edge
types, can be read off directly
phải conascháu
của
nó.
from pre and post numbers. Because of the depth-first exploration strategy, vertex
u is an ancestor of vertex v exactly in those cases where u is discovered first and
CuuDuongThanCong.com
/>
25 / 57