Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
【2019-06-19】アルゴリズム勉強会 - 最小全域木
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Hidehisa Arai
June 19, 2021
Technology
300
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
【2019-06-19】アルゴリズム勉強会 - 最小全域木
Hidehisa Arai
June 19, 2021
More Decks by Hidehisa Arai
See All by Hidehisa Arai
世界モデルにおける分布外データ対応の方法論
koukyo1994
7
2.2k
生成AIの二大潮流と自動運転
koukyo1994
22
25k
ICML2021論文読み会資料
koukyo1994
2
1.7k
Kaggle昔?話
koukyo1994
2
2.6k
コンペ中のコード、どうしてる?
koukyo1994
3
2.3k
変数間の関係を捉えたいあなたへ
koukyo1994
3
1.8k
脱! Deepでポン🎶ハイパラチューニング芸人を卒業するために
koukyo1994
7
4.9k
鳥蛙コンペ反省会資料
koukyo1994
3
1.5k
6th place solution to Cornell Birdcall Identification Challenge
koukyo1994
0
190
Other Decks in Technology
See All in Technology
Zenoh on Zephyr on LiteX
takasehideki
2
110
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
7.6k
FPC(フレキシブル)基板にZephyr実装してみた。
iotengineer22
0
170
データレイクの「見えない問題」を可視化する
sansantech
PRO
1
200
スタートアップにAmazon EKSは早すぎる? マルチプロダクト戦略を加速する Platform Engineeringの実践 / Is Amazon EKS Too Soon for Startups? Practical Platform Engineering to Accelerate a Multi-Product Strategy
elmodev09
1
1.8k
[AWS Summit Japan 2026]迷っているあなたへ_小さな一歩が、やがて自分を助けてくれる
sh_fk2
2
420
AIが自律的に回る開発ループを設計してチーム開発に組み込む
nekorush14
0
130
從開發到部署全都交給 AI:實作 AI 驅動的自動化流程
appleboy
0
170
気軽に使える"情報のハブ"としてのNotion活用 〜フロー情報の集積点 と、 Claude Code × Notion AI〜
syucream
1
200
「軸足」は 固定しなくていい - 熱量と強みで描く、しなやかなキャリアの形
kakehashi
PRO
1
270
徹底討論!ECS vs EKS!
daitak
3
1.7k
40代で“やっとエンジニアになれた”――閉じた学びを開き、空の青さを知る / 20260628 Naoki Takahashi
shift_evolve
PRO
4
890
Featured
See All Featured
[SF Ruby Conf 2025] Rails X
palkan
2
1.1k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Practical Orchestrator
shlominoach
191
11k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
It's Worth the Effort
3n
188
29k
Amusing Abliteration
ianozsvald
1
210
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
Test your architecture with Archunit
thirion
1
2.3k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
400
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
190
Crafting Experiences
bethany
1
190
Building the Perfect Custom Keyboard
takai
2
800
Transcript
2021/06/19 アルゴリズム勉強会 Hidehisa Arai 1
はじめに 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? => 最小全域木 2
ナイーブな考え方① 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? =>コストが小さい辺からとりあえず採用してみよう 途中経過 3
ナイーブな考え方② 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? =>コストが小さい辺からとりあえず採用してみよう 途中経過 次にコストの低い辺は これだが、採用すると 巡回が発生する・・・ =>巡回が発生しそうならスキップ! 4
ナイーブな考え方③ 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? =>コストが小さい辺からとりあえず採用してみよう いつ終わるの? => 全ノードを繋いだら終わり! 5
ナイーブな考え方 - アルゴリズムを書き下してみる • 入力の辺のコストが小さい順に採用していく ◦ コスト順にソートしておくと良さそう! • 巡回が発生しそうだったらスキップする
◦ 巡回が発生しそうってなに? • 全ノードを繋いだら終わり! ◦ 簡単に判別する方法はある? ◦ => 最終的には「木」になるのでノード数 - 1個の辺を採用 したら終わり! 水源 a b c e h 10 15 18 33 11 21 20 6 繋いでは ダメな辺 繋いでもOK な辺 6
ナイーブな考え方 - 巡回が発生しそうってなに? 水源 a b c e h 10
15 18 33 11 21 20 6 同じ部分グラフ= 連結成分 別の部分グラフ=連 結成分でない 両ノードが連結成分なエッジを選ば ないようにしたい =>連結成分の判定って? =>Union Find! 7
ナイーブな考え方 - アルゴリズムを書き下してみる • 入力の辺のコストが小さい順に採用していく ◦ コスト順にソートしておくと良さそう! • 巡回が発生しそうだったらスキップする
◦ 両ノードが連結成分なエッジをスキップする ◦ => Union Findで連結かどうか判定 • 全ノードを繋いだら終わり! ◦ 簡単に判別する方法はある? ◦ => 最終的には「木」になるのでノード数 - 1個の辺を採 用したら終わり! あり本間違えてる・・・? クラスカル(Kruskal)法といいます 8
クラスカル法 - 計算量 O(ElogE) O(V) O(Vα(n)) ※α(n)はアッカーマン関数の逆関数 O(ElogE) O(ElogV)
OR† † E < V2 なためlogE < logV2 = 2logV 9
別の考え方① 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? => 連結を保ちながらちょっとずつ木を大きくすることもできるのでは? 最初は重み最小の辺で良さそう、次は? 10
別の考え方② 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? => 連結を保ちながらちょっとずつ木を大きくすることもできるのでは? 最初は重み最小の辺で良さそう、次は? => すでに連結されている成分で最小コストの辺を繋ぐ 次にコストの低い辺は これだが、採用すると 巡回が発生する・・・ =>巡回が発生しそうならスキップ! 11
別の考え方③ 水源 a b d f c e h i
k l j g 10 15 18 33 11 21 20 6 85 9 56 2 22 77 5 39 30 81 14 12 38 41 67 水源から村の各戸に水道を引きたい。コスト最小になる引き方は? => 連結を保ちながらちょっとずつ木を大きくすることもできるのでは? いつ終わるの? => 全てのノードが繋がれば終わり! 12
別の考え方 - アルゴリズムを書き下してみる • 初めはコスト最小の辺を選ぶ(必須ではない) • すでに連結な成分に繋がっている辺の中で最小 コストの辺を選ぶ、ただし巡回が発生しそうな時は スキップ ◦
連結成分から伸びる辺で最小コストの辺ってどうやって 見つける? ◦ 巡回が発生しそうってなに? • 全ノードを繋いだら終わり! ◦ 簡単に判別する方法はある? ◦ => 最終的には「木」になるのでノード数 - 1個の辺を採用 したら終わり! d f h i k j g 9 2 22 5 81 41 最小がこれな ことをどう判定 する? 13
別の考え方 - 最小コストの辺をどう見つける? d f h i k j g
9 2 22 5 81 12 41 minCost[h] = 22 minCost[k] = 5 minCost[j] = 81 minCost[g] = 41 minCost[d] = 9 連結成分からそれ 以外のノードへの 最小移動コストを計 算しておき、その中 で最小の値をとる。 d f e h i k j g 9 2 22 5 81 41 67 minCost[e] = INF 連結成分から いけないノー ドはINF e 67 minCost[h] = 22 minCost[k] = 5 used[k] = true minCost[j] = 81 minCost[d] = 9 minCost[e] = INF minCost[g] = min(41, 12) 14
• すでに連結な成分に繋がっている辺の中で最小コストの辺を選ぶ、ただし巡回が 発生しそうな時はスキップ ◦ 連結成分から伸びる辺で最小コストの辺ってどうやって見つける? ▪ 連結成分からのそれ以外のノードへの最小コストを保持しておく ▪
連結成分から直接いけないノードへの最小コストはINF ▪ 辺を選択した後、最小コストを更新する必要がある • 全てのノードについて新しく追加されたノードからのコストと現在のminCostを比較する ◦ 巡回が発生しそうってなに? ▪ クラスカル法と違い、同じ連結成分かどうか調べる必要はない(連結成分は必ず一つの木) ▪ すでに連結成分になったかどうかを記録しておくだけでヨシ! ▪ 次の最小の辺は「まだ連結されていない辺」から選ぶ 別の考え方 - 最小コストの辺をどう見つける? 15
別の考え方 - 必要な要素を考える 連結成分からのそれ以外のノードへの最小コストを保持しておく連結 成分から直接いけないノードへの最小コストはINF => minCostの配列が必要。|minCost| = VでINFで初期化する。
すでに連結成分になったかどうかを記録しておくだけでヨシ! => 連結成分かどうかの配列が必要。|used| = Vでfalseで初期化する。 次の最小の辺は「まだ連結されていない辺」から選ぶ => 全てのノードvについてused[v] = falseかつminCost[v]が最小かを確認 全てのノードについて新しく追加されたノードからのコストと現在のminCostを比較する => ノードからノードへのコストを保持する行列Costが必要。辺が実際には存在し ないところはINFで初期化する。 => 全てのノードvについて現在のminCost[v]とCost[v][u]の比較をし、Cost[v][u] の方が小さければminCost[v] = Cost[v][u]となる。 16
別の考え方 - アルゴリズム全体 ノードからノードへのコストを保持する行列が必 要。辺が実際には存在しないところはINFで初期 化する。 minCostの配列が必要。|minCost| = VでINFで初 期化する。
連結成分かどうかの配列が必要。|used| = Vで falseで初期化する。 全てのノードvについてused[v] = falseかつ minCost[v]が最小かを確認 全てのノードvについて現在のminCost[v]と Cost[v][u]の比較をし、Cost[v][u]の方が小さけ ればminCost[v] = Cost[v][u]となる。 17 プリム(Prim)法といいます
別の考え方 - 計算量 O(V) V回実行される 単体でO(V) 単体でO(V) O(V2) O(V2) V×
V× O(V2) 18
別の考え方 - 計算量改善 プライオリティキューを使う => O(logV) 隣接リストを使う O((V+E)logV) 19