1 アルゴリズムとデータ 構造 第10回グラフとネットワークのアルゴリズム(1) 2015/12/16 アルゴリズムとデータ構造 2015 2 グラフとネットワーク グラフ(graph)とは 頂点(vertex)の集合Vと辺の集合E⊆V×Vの組(V,E) 無向グラフ (undirected graph) v0 e0 e5 v1 v4 e2 e4 e1 v e3 v 2 有向グラフ (directed graph) v0 e0 e5 v1 v4 e2 e1 e4 e0=(v0,v1), e1=(v1,v2), e2=(v0,v2), e3=(v2,v3), e4=(v3,v4), e5=(v4,v0) 辺(u,v)は有向グラフの場合、 頂点uから頂点vへの辺を表す。 v2 e3 v3 3 V={v0,v1,v2,v3,v4,v5} E={e0,e1,e2,e3,e4,e5} 重み付きグラフ(weighted graph,ネットワーク(network))とは 各辺に重み(整数値または実数値)が付いたグラフ 2 2 4 3 2015/12/16 2 2 2 1 4 3 2 1 無向グラフでは 辺(u,v)を{u,v}と 書く場合もある。 アルゴリズムとデータ構造 2015 隣接行列と隣接リスト 3 v0 v0 V={v0,v1,v2,v3,v4,v5} v1 E={(v0,v1),(v1,v2),(v0,v2), (v2,v3),(v3,v4),(v4,v0)} v4 2 v1 2 v4 4 3 v2 頂点の数をn、辺の数をmとする。 v3 1 v2 2 v3 隣接行列(adjacency matrix) v0 v1 v2 v3 v4 v0 0 0 0 0 1 v1 1 0 0 0 0 v2 1 1 0 0 0 v3 0 0 1 0 0 v4 0 0 0 1 0 1 ((vi,vj)∈E) A(i,j)= 0 ((vi,vj)∈E) 利点 ・2頂点間に辺があるか否かを O(1)時間でチェック可能 欠点 ・O(n2)の記憶領域が必要。 ・1つの頂点の隣接頂点をすべて 求めるのにO(n)時間必要。 v0 v1 v2 v3 v4 v0 0 0 0 0 2 v1 2 0 0 0 0 v2 4 3 0 0 0 v3 0 0 2 0 0 v4 0 0 0 1 0 隣接リスト(adjacency list) 1 2 2 4 NULL 利点 ・O(m)の記憶領域で済む。 0 NULL 2 3 NULL ・1つの頂点の隣接頂点を全て求める 1 NULL 3 2 NULL のに、その頂点の隣接頂点数の定数 2 NULL 4 1 NULL 倍時間で可能。 3 NULL 0 2 NULL 欠点 ・2頂点間に辺があるか否かをチェック 4 するのに隣接頂点の数のオーダーの 時間が必要 無向グラフの場合は、各辺が両方向の2辺からなる有向グラフとして隣接行列、隣接リストを作成すればよい。 0 1 2 3 4 2015/12/16 1 2 3 4 0 2 NULL アルゴリズムとデータ構造 2015 無向グラフの探索 4 連結無向グラフのすべての頂点を訪れる探索法には主に次の2つがある。 1.深さ優先探索(Depth-First Search, DFS) 2.幅優先探索(Breadth-First Search, BFS) v0 [深さ優先探索のアルゴリズム] Step 1 vの状態←未訪問 for all v∈V Step 2 v0←適当な頂点(出発点) Step 3 dfs(v0)を実行 dfs(v:頂点) Step 1 vの状態←訪問済 Step 2 vの全ての隣接頂点uに対して以下のことを行う。 if uの状態=未訪問 then dfs(u)を実行 [幅優先探索のアルゴリズム] Step 1 vの状態←未訪問 for all v∈V Step 2 適当な頂点v0(出発点)をキューqに入れる v0の状態←訪問済 Step 3 if qが空 then 停止 Step 4 qから頂点を1つ取り出してそれをvとする。 Step 5 vの全ての隣接頂点uに対して以下のことを行う。 if uの状態=未訪問 then uの状態←訪問済 uをqに入れる end if Step 6 Step 3へ戻る 2015/12/16 v1 v7 v2 v5 v3 v6 v4 q v42376510 v26375 v2763 v237 v2 v0 v1 v7 v2 v5 v3 v6 v4 最悪/平均時間計算量O(n+m) (n:頂点数、m:辺の数) アルゴリズムとデータ構造 2015 最小スパニング木 5 グラフG’はグラフG=(V,E)のスパニング木(全域木、spanning tree) def ⇔G’はGのすべての頂点を含む部分グラフ(V,T)で木になっているもの def (グラフGは木 ⇔ Gは閉路のない連結無向グラフ) 深さ優先のスパニング木(太線) 幅優先のスパニング木(太線) v0 v1 v1 v7 v7 v2 v2 v3 v0 v4 v5 v6 v3 v4 v5 v6 グラフG’は重み付きグラフG=(V,E)の最小スパニング木(minimum spanning tree) def ⇔Gのスパニング木で、含まれる辺の重みの総和が最小のもの G 1 2 2 3 最小スパニング木を求めるアルゴリズム Gの最小スパニング木 1 5 クラスカル(Kruskal)のアルゴリズム 2 4 2 4 7 応用として、通信網の設計、ガス・水道の配管等がある。 2015/12/16 プリム(Prim)のアルゴリズム 最悪時間計算量: O(m log n) (n: 頂点数, m: 辺の数) アルゴリズムとデータ構造 2015 6 クラスカルのアルゴリズム [考え方] 重みが小さい辺から選択していく。ただし、選択することに より閉路ができる場合は選択しない。 Joseph B. Kruskal 1928-2010 , USA [例] ① G 1 2 ② 辺の重み ① 1 ⑥ 5 3 ④ 7 ⑦ 2 ③ 1 5 2 4 ⑤ 2 3 7 1 5 2 4 2 ② 3 4 7 2 1 5 3 7 2 ③ 5 2 4 2 3 7 辺の重みの順位 [アルゴリズム] Step 1 T←φ Step 2 辺の配列eを重みの小さい順に整列 Step 3 i=0,1,…,m-1の順で次のことを行う。 if T∪{e[i]}は閉路を含まない then T←T∪{e[i]} 2015/12/16 アルゴリズムとデータ構造 2015 4 ⑤ 7 クラスカルのアルゴリズムのベースとなる補題 次の補題が成り立つ。 E−T(または E\Tとも表 記)は集合 間の演算で EからTに含 まれる要素 を除いた集 合 補題 (V,E)を連結無向グラフとし、T⊆Eとする。このとき、以下の条件は部分 グラフ(V,T)が(V,E)の最小スパニング木であるための必要十分条件である。 条件 部分グラフ(V,T)は(V,E)のスパニング木で、全てのe∈E-Tに対して w(e)≧w(e’) for all e’∈CT(e) ただし、w(e)は辺eの重みを表し、CT(e)は辺e∈E-TとTの辺によって作られ る閉路に含まれるTの辺の集合を表すものとする。 e e G 1 1 5 2 2 3 4 2015/12/16 2 3 7 細線:E−T 1 5 2 7 太線:T 1 5 5 2 4 2 3 2 4 7 2 3 7 4 e 黄色線:CT(e) アルゴリズムとデータ構造 2015 8 クラスカルのアルゴリズムが正しいことの証明 (証明) クラスカルのアルゴリズムにより求めた辺の集合をT0とする。このとき、補題の条件が 成り立っていることを示せばよい。 v まず、(V,T0)がスパニング木であることを示す。(V,T0)は明らかに閉路を持たない。 いま、T0に含まれる辺の端点の集合をV’とし、V’=Vを示す。 u V’ V’≠Vとすれば、ある頂点v∈V-V’が存在する。(V,E)は連結であるので、ある 頂点u∈V’が存在して、V’の頂点を経由しないでvへ到達する路が存在する。 その路に属する辺をT0に加えても閉路はできない。これはアルゴリズムの e CT0(e) 「閉路ができない限り辺を加える」という動作に矛盾する。 ’ e よってV’=Vとなり、(V,T0)はスパニング木であることが示された。 w(e)<w(e’) 次に、全てのe∈E-T0、全てのe’∈CT0(e)に対してw(e)≧w(e’)が成り立つことを示す。 あるe∈E-T0が存在して、あるe’∈CT0(e)に対してw(e)<w(e’)が成り立ったとする。 すると、アルゴリズムのStep 3においてT∪{e}が閉路を持つか否かチェックしたときには、 Tにはe’は含まれていないので、T∪{e}は閉路を持たないことになりT0がeを含んでいな いことに矛盾する。 よって全てのe∈E-T0、全てのe’∈CT0(e)に対してw(e)≧w(e’)が成り立つことが示された。 (証明終り) 2015/12/16 アルゴリズムとデータ構造 2015 9 補題の証明 (証明) (⇒) (V,T)が最小スパニング木なのに条件を満たさないと仮定する。すると e あるe∈E-Tが存在し、あるe’∈CT(e)に対してw(e)<w(e’)が成り立つ。 CT0(e) (V,T∪{e}-{e’})は(V,E)のスパニング木であり、(V,T)よりも辺の重みの和が ’ e 小さい。これは(V,T)が最小スパニング木であることに矛盾する。よって、 w(e)<w(e’) (V,T)が最小スパニング木であれば、条件を満たす。 ( )最小スパニング木の1つを(V,T*)とする。条件を満たす(V,T)の辺の重みの和 は(V,T*)の辺の重みの和に等しいことを示す。e∈T*-Tが存在したとする。 eにより分かれる2つの連結成分を(V0,T*0),(V1,T*1)とすると、e’∈CT(e)で 2つの連結成分(V0,T*0),(V1,T*1)を跨ぐ辺e’∈Tが存在する。(V,T)は条件 を満たしているのでw(e)≧w(e’)が成り立つのでT’=T*∪{e’}-{e}とすれば、 T’の重みの総和はT*の重みの総和以下になる。T*は最小スパニング木なので、 T’もT*と重みの総和が等しい最小スパニング木であり、|T’-T|<|T*-T|を満たす。 ただし、|S|は集合Sの要素数を表すものとする。したがってT’をT*として同じ 操作を繰り返すとT’=Tとなり、TもT*と重みの総和が等しい最小スパニング木で あることが示される。 (証明終り) 2 e’ T T* 2015/12/16 3 e 2 3 2 2 3 e’ 3 e 3 アルゴリズムとデータ構造 2015 10 T∪{e}が閉路を含むか否かを効率的にチェックする方法 [考え方] 頂点の集合Vをグラフ (V,T)において連結している成 分に分解した場合に、eの両端 が同じ成分に属している(閉路 を含む)か否(閉路を含まな い)かをチェックする。 両端が同じ成分に属している →加えると閉路を含むグラフになる 両端が異なる成分に属している →加えても閉路を含むグラフにならない 頂点集合Vをグラフ(V,T)の連結成分に分割することによりできる集合族S0,S1,…,Skを 保持し、次の2つの手続きを用意する。 find(a) : a∈Siと成るような集合Siの名前を返す。 union(ID0,ID1) : 名前がID0, ID1である集合SiとSjを統合して1つの集合にする。 e[i]=(e[i].from,e[i].to)とすれば、上の2つの手続きを使ってStep 3 は次のように書ける。 Step 3 i=0,1,2,…,m-1の順で次のことを行う。 ID0←find(e[i].from) ID1←find(e[i].to) if(ID0≠ID1) then T←T∪{e[i]} union(ID0,ID1) end if 2015/12/16 アルゴリズムとデータ構造 2015 11 集合族のfind, unionに適したデータ構造 それぞれの集合を、要素(頂点ID)を節点のラベルとする木で表現し、 根のラベルを集合の名前とする。 名前が7の連結成分 [例] 0 ② 1 7 0 ③ ④ ① 2 5 3 ⑦ ⑥ 6 4 ⑤ 名前が2の連結成分 find(i) : ラベルiの節点から親を辿り根のラベルを返す Union(i,j) : ラベルiとラベルjを根に持つ木をマージする。ただし、高さが低い方 の木の根を高い方の木の根の子とする。(高さが同じ場合はどちらでもよい) 最悪時間計算量 find: O(log n) (n:要素数) union: O(1) 2015/12/16 ② Union(2,7)に統合された木 ③ ④ ① ⑦ ⑤ 0 ⑥ アルゴリズムとデータ構造 2015 12 find(i)の最悪時間計算量がO(log n)であることの証明 集合族のfind(i)の時間計算量は、ラベルiの節点の深さに比例するので、 根のみのn個の木から出発してunionを何度か繰り返し適用した場合、作成される 任意の木の高さkはlog2n以下であることを示せばよい。 これには以下のことを示せばよい。 unionにより作られる高さkの木は節点数が2k以上 ---------------------------① なぜならば、①が成り立つのに高さがlog2nより大きいとすると節点数がn=2log2nよ り大きいことになり矛盾するからである。 ①を数学的帰納法で証明する。 k=0のときは高さが0の木の節点数は1であるから①は成り立つ。 k=h(h≧0)のとき①が成り立つと仮定する。 k=h+1の木Tの根のラベルをiとする。根のラベルがiの木の高さがh+1になったの はラベルiの木の高さがhのとき、高さhの木をマージしたunionを行った場合であり、 それ以外はあり得ない。このとき、高さk=hの木に対しては①が成り立つという仮 定から、マージ後の木の節点数は2・2h=2h+1以上となる。Tは、その後unionを何度 か適用された木かもしれないが、unionにより節点数は増えるだけなので、Tの節 点数も2h+1以上である。 したがって、k=h+1のときにも①が成り立つ。 (証明終り) 2015/12/16 アルゴリズムとデータ構造 2015 13 クラスカルのアルゴリズムの最悪時間計算量はO(m log n) (証明) Step 1は定数ステップ。 Step 2はm個のソートなのでO(m log m)であるが、m≦n2なのでO(m log n)。 Step 3はn-1回のunionと高々2m回のfindを実行するからO(n+m log n)。 連結グラフで考えているのでn-1≦mであるからStep 3はO(m log n)で実行できる。 したがって全体でもO(m log n)で実行できる。 (証明終り) 2015/12/16 アルゴリズムとデータ構造 2015
© Copyright 2025 ExpyDoc