5. 2011/4/27 アルゴリズムとデータ構造 13 5
全ての重みが1の最短経路問題
全ての辺の重みが 1 の場合,最短経路問題は
,頂点 u と v を最も少ない個数の辺で結ぶパ
スを見つけることになる.
この場合,幅優先探索によって解ける
確認問題:上記を確認せよ
6. 2011/4/27 アルゴリズムとデータ構造 13 6
単一出発点の問題
Dijkstra のアルゴリズム
考え方:
出発点から頂点 v への最短経路について, v の 1 つ手前の頂点までの経路は
,その頂点までの最短経路となっている.
戦略:
各頂点への最短経路を出発点に近いところから一つずつ確定していく
最短経路が確定した頂点の中から,次に近い頂点を探して,確定する
確定した頂点から出ている辺の次の頂点の距離が,より短かくなれば更新す
る.
出発点
u
v
t
最短経路
最短経路
距離 =100
距離 =102
10
5
距離 =107
7. 2011/4/27 アルゴリズムとデータ構造 13 7
Dijkstra 法の動作
a
b
d
c
e
10
1
5
2 3 4 6
2
9
7
0
∞ ∞
∞ ∞
a
b
d
c
e
10
1
5
2 3 4 6
2
9
7
0
10 ∞
5 ∞
a
b
d
c
e
10
1
5
2 3 4 6
2
9
7
0
8 14
5 7
a
b
d
c
e
10
1
5
2 3 4 6
2
9
7
0
8 13
5 7
a
b
d
c
e
10
1
5
2 3 4 6
2
9
7
0
8 9
5 7
a
b
d
c
e
10
1
5
2 3 4 6
2
9
7
0
8 9
5 7
8. 2011/4/27 アルゴリズムとデータ構造 13 8
Dijkstra 法の Python 風コード
def dijkstra(G, s):
V = set() # 空集合
U = list(range(len(G.vertices)))
initialize_single_source(G, s)
while len(U) > 0:
p = remove_mindist(U) # の中で最小の dist を持つ頂点を取
り出す
V.add(p)
for e in G.edges[p]: # p から出ているそれぞれの辺 :
q = e.dest
if q in U:
G.vertices[q].dist = min(G.vertices[q].dist,
G.vertices[p].dist + e.weight)
def initialize_single_source(G, s):
for i in range(len(G.vertices)):
G.vertices[i].dist = 999999 # ∞ の代用
G.vertices[s].dist = 0
最短経路を求める場合
,ここで,直前の頂点
を記録しておけば良い
9. 2011/4/27 アルゴリズムとデータ構造 13 9
Dijkstra 法の正しさの証明
U 内の各頂点には, V に属する頂点だけを経由してその頂点に
達する最短のパスの長さ distance が記録されている
アルゴリズムの擬似コードから明らか
U の中から最小の distance を持つ頂点 p を選んだときに, p ま
での最短経路が, V に属する頂点しか経由しないことを証明す
る
背理法による:
もし, V に属さない点を経由して p に至るパスがあり, V から直接
p に達するパスよりも短いとする.このとき,このパス上で V の外
にある最初の頂点を q とする
頂点 q から p までのパスの長さは 0 以上なので,出発点から q に行
くパスの長さの方が,出発点から p に行くまでのパスの長さよりも
短くなくてはならない.これは,最小の distance を持つ頂点 p を選
んだ,とする仮定と矛盾する
注意:
Dijkstra 法が正しく動くためには,辺の重みが負ではないことが
条件.
15. 2011/4/27 アルゴリズムとデータ構造 13 15
Prim 法
最小全域木を求めるアルゴリズム
基本的な戦略:
1つの辺からはじめて,全頂点を覆うまで辺を 1 本ずつ付け加え,木を拡大
していく
def prim(G):
U = set()
V = set(G.vertices)
initialize_single_source(G, 0)
while len(U) != 0:
p = remove_mindist(U) # U の中で最小の dist を持つ頂点
を取り出す
V = V.add(p)
for e in p.edges: # p から出ているそれぞれの辺
q = e.dest
if q in U:
G.vertices[q].dist = min(G.vertices[q].dist,
e.weight)
ここだけ
Dijkstra 法と異
なる
16. 2011/4/27 アルゴリズムとデータ構造 13 16
練習問題
以下のグラフに対して, Prim 法を適用し,
最小全域木を求めよ
別の頂点を出発点としたときでも,同じ最小全域
木が得られることを確認せよ
A
B
C
D E
F
G
7 8
5 5
79
15
6 8 9
11
17. 2011/4/27 アルゴリズムとデータ構造 13 17
Prim 法の正しさの証明
各ステップで集合 V と U を結ぶ辺のうち,重み最小のものを選んでい
る.
この辺を e とし, e を含む最小木が必ず存在することを背理法で証明する
e を含まない最小木があったとして,それを f とする
f の重みは e の重み以上である
この最小木には,辺 e の両端の頂点 p, q を結ぶ道があるので,これに e を
加えると閉路ができる.
そこから f を除けば,再び全域木が得られるが,こちらの方が重みの総和が
小さい
e
V U
f
qp
18. 2011/4/27 アルゴリズムとデータ構造 13 18
Kruskal 法
各頂点をそれぞれ独立した集合とみなす
重みの小さい辺から順に調べていき,異なる集合同士を結ぶ辺
があれば,この辺を最小木の辺の一つとして採用し 2 つの集合
を合併する
最終的に集合が1つになるまで,上記を繰り返す
練習問題:以下のグラフに対して, Kruskal 法を適用してみよ
A
B
C
D E
F
G
7 8
5 5
79
15
6 8 9
11