第12回グラフとネットワークのアルゴリズム(1)kida/lecture/alg2019-12.pdf講義「アルゴリズムとデータ構造」...
TRANSCRIPT
講義「アルゴリズムとデータ構造」
第12回 グラフとネットワークのアルゴリズム(1)
大学院情報科学研究院 情報理工学部門情報知識ネットワーク研究室
喜田拓也
2019/5/22講義資料
今日の内容
2
グラフとはなんでグラフ?グラフの数学的な定義,ネットワーク(重み付きグラフ)の定義
グラフデータの取り扱いのしかた隣接行列による表現隣接リストによる表現
グラフの探索の仕方深さ優先探索幅優先探索
ケーニヒスベルクの橋問題
プレーゲル川
なんでグラフ?
3
モノとモノのつながりを簡潔に記述し,解析できる!
世の中のすべてはグラフ!
無向グラフ(undirected graph) 有向グラフ(directed graph)
例) 𝑉𝑉 = 𝑣𝑣0, 𝑣𝑣1, 𝑣𝑣2, 𝑣𝑣3, 𝑣𝑣4 ,𝐸𝐸 = {𝑒𝑒0, 𝑒𝑒1, 𝑒𝑒2, 𝑒𝑒3, 𝑒𝑒4, 𝑒𝑒5}のとき
ただし,𝑒𝑒0 = 𝑣𝑣0, 𝑣𝑣1 , 𝑒𝑒1 = 𝑣𝑣1, 𝑣𝑣2 , 𝑒𝑒2 = 𝑣𝑣0, 𝑣𝑣2 ,𝑒𝑒3 = 𝑣𝑣2, 𝑣𝑣3 , 𝑒𝑒4 = 𝑣𝑣3, 𝑣𝑣4 , 𝑒𝑒5 = (𝑣𝑣4, 𝑣𝑣0)
有向グラフの場合,辺(𝑢𝑢,𝑣𝑣)は頂点𝑢𝑢から頂点𝑣𝑣への辺(有向辺)を表す無向グラフでは辺(𝑢𝑢, 𝑣𝑣)を{𝑢𝑢,𝑣𝑣}と書く場合もある
グラフ(graph)とは
4
頂点(vertex)の集合𝑉𝑉と
辺(edge)の集合𝐸𝐸 ⊆ 𝑉𝑉 × 𝑉𝑉の組(𝑉𝑉,𝐸𝐸)のこと
𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣4𝑒𝑒0
𝑒𝑒1𝑒𝑒2
𝑒𝑒3
𝑒𝑒4
𝑒𝑒5𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣4𝑒𝑒0
𝑒𝑒1𝑒𝑒2
𝑒𝑒3
𝑒𝑒4
𝑒𝑒5
ネットワーク(network)とは
5
各辺𝑒𝑒𝑖𝑖に重み(整数値または実数値)𝑤𝑤𝑖𝑖が付いたグラフ
のこと.重み付きグラフ(weighted graph)ともいう
例) 𝑉𝑉 = 𝑣𝑣0, 𝑣𝑣1, 𝑣𝑣2, 𝑣𝑣3, 𝑣𝑣4, 𝑣𝑣5 ,𝐸𝐸 = {𝑒𝑒0, 𝑒𝑒1, 𝑒𝑒2, 𝑒𝑒3, 𝑒𝑒4, 𝑒𝑒5}のとき
ただし,𝑒𝑒0 = 𝑣𝑣0, 𝑣𝑣1 , 𝑒𝑒1 = 𝑣𝑣1, 𝑣𝑣2 , 𝑒𝑒2 = 𝑣𝑣0, 𝑣𝑣2 ,𝑒𝑒3 = 𝑣𝑣2, 𝑣𝑣3 , 𝑒𝑒4 = 𝑣𝑣3, 𝑣𝑣4 , 𝑒𝑒5 = (𝑣𝑣4, 𝑣𝑣0)𝑤𝑤0 = 2,𝑤𝑤1 = 3,𝑤𝑤2 = 4,𝑤𝑤3 = 2,𝑤𝑤4 = 1,𝑤𝑤5 = 2
𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣42
34
21
2𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣42
34
21
2
無向ネットワーク 有向ネットワーク
𝐴𝐴 𝑖𝑖, 𝑗𝑗 = �1 𝑣𝑣𝑖𝑖 ,𝑣𝑣𝑗𝑗 ∈ 𝐸𝐸 ,
0 𝑣𝑣𝑖𝑖 ,𝑣𝑣𝑗𝑗 ∉ 𝐸𝐸)
𝑣𝑣0 𝑣𝑣1 𝑣𝑣2 𝑣𝑣3 𝑣𝑣4
※ 無向グラフの場合は,各辺を両方向の2辺からなる有向グラフとみなして表現する
隣接行列(adjacency matrix)による表現
6
𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣4𝑒𝑒0
𝑒𝑒1𝑒𝑒2
𝑒𝑒3
𝑒𝑒4
𝑒𝑒5
𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣42
34
21
2
有向グラフについて,各辺の有無を行列で表したもの
(有向ネットワークの場合は重みを要素とした行列)
0 1 1 0 00 0 1 0 00 0 0 1 00 0 0 0 11 0 0 0 0
𝑣𝑣0𝑣𝑣1𝑣𝑣2𝑣𝑣3𝑣𝑣4
𝑣𝑣0 𝑣𝑣1 𝑣𝑣2 𝑣𝑣3 𝑣𝑣40 2 4 0 00 0 3 0 00 0 0 2 00 0 0 0 12 0 0 0 0
𝑣𝑣0𝑣𝑣1𝑣𝑣2𝑣𝑣3𝑣𝑣4
𝐴𝐴 𝑖𝑖, 𝑗𝑗 =
�𝑤𝑤𝑘𝑘 𝑣𝑣𝑖𝑖 , 𝑣𝑣𝑗𝑗 = 𝑒𝑒𝑘𝑘 ∈ 𝐸𝐸 ,
0 𝑣𝑣𝑖𝑖 ,𝑣𝑣𝑗𝑗 ∉ 𝐸𝐸)
01234
2 NULL12 NULL
3 NULL
4 NULL
0 NULL
01234
2 NULL33 NULL24 NULL10 NULL2
1 2 2 NULL4
隣接リスト(adjacency list)による表現
7
有向グラフについて,各辺の有無を連結リストの配列で
表したもの(ネットワークの場合は重みを付加する)
※ 無向グラフの場合は,各辺を両方向の2辺からなる有向グラフとみなして表現する
𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣4𝑒𝑒0
𝑒𝑒1𝑒𝑒2
𝑒𝑒3
𝑒𝑒4
𝑒𝑒5
𝑣𝑣0
𝑣𝑣1
𝑣𝑣2 𝑣𝑣3
𝑣𝑣42
34
21
2
重みは第2要素に格納
隣接行列と隣接リストの利点,欠点
8
利点 欠点
2頂点間に辺があるか否か
をO(1)時間でチェック可能
O(𝑛𝑛2)の記憶領域が必要
1つの頂点の隣接頂点を求
めるのにO(𝑛𝑛)時間必要
隣
接
行
列
隣
接
リ
スト
利点 欠点
O(𝑚𝑚)の記憶領域で済む 2頂点間に辺があるか否かをチェックするのに,隣接頂点数に比例した時間が必要
1つの頂点の隣接頂点を求めるのは,その隣接頂点数に比例した時間だけで可能
連結リストを線形探索するから
グラフの探索
9
頂点数𝑛𝑛の入力グラフ 𝐺𝐺 = (𝑉𝑉,𝐸𝐸) が与えられたとき,そのすべての頂点を訪問すること.
• 入力グラフは,隣接リスト表現で与えられるとする
• 出力として,訪問した頂点の並びを出力する.ただし,同じ頂点は2回以上重複して出力しないものとする
応用
• ゲーム(迷路,盤ゲーム),画像処理,etc…
探索法には主に次の2つがある。
1.幅優先探索(Breadth-First Search, BFS)2.深さ優先探索(Depth-First Search, DFS)
各種グラフ処理の基本アルゴリズム
幅優先探索の考え方
10
基本的なアイデア
• ソース(スタート地点となる頂点)𝑠𝑠から「波」を伝播させて,
波の「先端」(frontier)を横断的に訪問(展開)することで,
すべての頂点を探索する
アルゴリズムの動き
1. ソース𝑠𝑠を一つ決め,キュー(FIFO)に入れる
2. キューから一つ頂点𝑣𝑣を取り出して𝑣𝑣をたどる
3. 𝑣𝑣の隣接頂点のうち未訪問(かつ未発見)の頂点をすべて
キューに入れる
4. キューが空になるまで2と3を繰り返す
特長
• ソースから近い順番に訪問できる
ab
cde
f g
h
幅優先探索アルゴリズム BFS
11
色 意味
白 未訪問
赤 発見済
黒 訪問済
頂点𝑣𝑣の状態の意味Procedure BFS (𝐺𝐺: グラフ)1: for each 𝑣𝑣 ∈ 𝑉𝑉 do 状態[𝑣𝑣] ← 白; 2: Q ← 空のキュー; 3: 状態[𝑠𝑠] ← 赤; // ソース𝑠𝑠は適当な頂点4: Q.Enqueue(𝑠𝑠); 5: while (Q が空でない) do begin6: 𝑣𝑣 ← Q.Dequeue(); 7: 𝑣𝑣を出力する; // その頂点を処理8: for each (𝑣𝑣の隣接頂点𝑢𝑢) do9: if (状態[𝑢𝑢]=白 & 状態[𝑢𝑢]≠赤) then10: 状態[𝑢𝑢] ← 赤; 11: Q.Enqueue(𝑢𝑢); 12: end if13: 状態[𝑣𝑣] ← 黒; 14: end while
最悪/平均の時間計算量はO(𝑛𝑛 + 𝑚𝑚)(𝑛𝑛:頂点数,𝑚𝑚:辺の数)
幅優先探索の計算例
12
問い: 右図の隣接リスト表現で与えられるグラフ𝐺𝐺のBFSで出力される頂点リストを与えよ.
解答: a, b, f, g, h, d, c, e
頂点 隣接リストa b, f, g, hb d, c, fc d, ed nulle nullf nullg nullh g
𝐺𝐺の隣接リスト表現
ステップ訪問頂点𝑣𝑣
𝑣𝑣の隣接頂点リスト
キューQの内容
0 - a1 a b, f, g, h b, f, g, h2 b d, c, f f, g, h, d, c3 f null g, h, d, c4 g null h, d, c5 h g d, c6 d null c7 c d, e e8 e null -
※ 下線は次に取り出される頂点.赤字は新たに追加された頂点.
ab
cde
f g
h
深さ優先探索の考え方
13
基本的なアイデア
• ソース(スタート地点となる頂点)𝑠𝑠から,未発見の頂点を
優先的に可能な限り深い方へと探索する
アルゴリズムの動き
1. ソース𝑠𝑠を一つ決め,スタック(FILO)に入れる
2. スタックから一つ頂点𝑣𝑣を取り出して𝑣𝑣をたどる
3. 𝑣𝑣の隣接頂点のうち未訪問(かつ未発見)の頂点をすべて
スタックに入れる
4. スタックが空になるまで2と3を繰り返す
ab
cde
f g
h特長
• メモリ使用量が少なくなることが多い
• 特に再帰版は実装が簡単
深さ優先探索アルゴリズム DFS
14
色 意味
白 未訪問
赤 発見済
黒 訪問済
頂点𝑣𝑣の状態の意味
最悪/平均の時間計算量はO(𝑛𝑛 + 𝑚𝑚)(𝑛𝑛:頂点数,𝑚𝑚:辺の数)
Procedure DFS (𝐺𝐺: グラフ)1: for each 𝑣𝑣 ∈ 𝑉𝑉 do 状態[𝑣𝑣] ← 白; 2: Q ← 空のスタック; 3: 状態[𝑠𝑠] ← 赤; // ソース𝑠𝑠は適当な頂点4: Q.Push(𝑠𝑠); 5: while (Q が空でない) do begin6: 𝑣𝑣 ← Q.Pop(); 7: 𝑣𝑣を出力する; // その頂点を処理8: for each (𝑣𝑣の隣接頂点𝑢𝑢) do9: if (状態[𝑢𝑢]=白 & 状態[𝑢𝑢]≠赤) then10: 状態[𝑢𝑢] ← 赤; 11: Q.Push(𝑢𝑢); 12: end if13: 状態[𝑣𝑣] ← 黒; 14: end while
深さ優先探索の計算例
15
問い: 右図の隣接リスト表現で与えられるグラフ𝐺𝐺のDFSで出力される頂点リストを与えよ.
解答: a, h, g, f, b, c, e, d
頂点 隣接リストa b, f, g, hb d, c, fc d, ed nulle nullf nullg nullh g
ステップ訪問頂点𝑣𝑣
𝑣𝑣の隣接頂点リスト
スタックQの内容
0 - a1 a b, f, g, h b, f, g, h2 h g b, f, g3 g null b, f4 f null b5 b d, c, f d, c6 c d, e d, e7 e null d8 d null -
※ 下線は次に取り出される頂点.赤字は新たに追加された頂点.
ab
cde
f g
h
深さ優先探索アルゴリズム DFS (再帰版)
16
Procedure DFS (𝐺𝐺: グラフ)1: for each (𝑣𝑣 ∈ 𝑉𝑉) do 状態[𝑣𝑣] ← 白; 2: 𝑠𝑠 ←ソース頂点; // ソース𝑠𝑠は適当な頂点3: Visit(𝑠𝑠); // 再帰手続きの開始
Procedure Visit(𝑣𝑣: 頂点)1: 𝑣𝑣を出力する; 2: 状態[𝑣𝑣] ← 黒; 3: for each (𝑣𝑣の隣接頂点𝑢𝑢) do4: if (状態[𝑢𝑢]=白 & 状態[𝑢𝑢]≠赤) then5: Visit(𝑢𝑢); //再帰呼び出し6: end if6: end for
色 意味
白 未訪問
黒 訪問済
頂点𝑣𝑣の状態の意味
このアルゴリズム場合,隣接リストの順に未訪問の頂点を可能な限り深く探索するので,スタックを使うアルゴリズムとは出力順が異なる点に注意
【練習】 先の例のグラフ𝐺𝐺に対してどのような順番で出力されるか?