1. 直線でつながる
  2. 別成分 -> false
  3. s == t (自分自身)
  4. 孤立 t
  5. サイクルあり
  6. 辺なし、s != t
コース一覧
コンピューターサイエンス上級:アルゴリズムとデータ構造
グラフのパス存在判定

コンピューターサイエンス上級:アルゴリズムとデータ構造

探索、ソート、木、グラフ、動的計画法、貪欲法など、競技プログラミングや技術面接で問われる高度なアルゴリズムとデータ構造を学べるコースです。基本的な CS の知識を持ち、アルゴリズム力を伸ばしたい学習者や、外資・大手の技術面接対策をしたい方を対象としています。約 13 時間 (1 日 30 分 × 26 日) で 50 レッスンを修了でき、修了後はコーディング面接の実装問題を構造的に解けるようになります。

1
連結リスト
01. リンクリスト構築と長さの計算5分
02. リンクリストの反転5分
03. リンクリストのサイクル検出5分
04. ソート済みリンクリストの merge5分
05. リンクリストの中央ノード取得5分
06. ソート済みリストの重複削除5分
07. 第1章まとめクイズ5分
2
二分木
01. 二分木の in-order 走査5分
02. 二分木の pre-order 走査5分
03. 二分木の post-order 走査5分
04. 二分木の幅優先走査 (BFS)5分
05. 二分木の高さ5分
06. 二分木の平衡判定5分
07. 第2章まとめクイズ — 二分木5分
3
探索木 (BST)
01. BST に値を挿入する5分
02. BST から値を検索する5分
03. BST の最小値と最大値5分
04. BST 妥当性チェック5分
05. BST で k 番目に小さい値5分
06. BST から値を削除する5分
07. 第 3 章 まとめクイズ5分
4
ハッシュとセット
01. hashmap で頻度集計5分
02. キーでグループ化5分
03. two sum (hash で O(n))5分
04. 部分配列の和 = k の個数5分
05. 最長連続部分列5分
06. 集合の積 (intersection)5分
07. 第4章まとめクイズ5分
5
グラフ
01. グラフ BFS で連結成分サイズを求める5分
02. グラフ DFS で連結成分の数を数える5分
03. グラフのパス存在判定5分
04. BFS で最短経路の長さを求める5分
05. トポロジカルソート5分
06. 2 部グラフ判定5分
07. ダイクストラ法 — 重み付きグラフの最短経路15分
08. 第5章まとめクイズ — グラフ5分
6
動的計画法 (上級)
01. 編集距離 (レーベンシュタイン距離)5分
02. 最長増加部分列(LIS)の解法 ── AOJ 2430 対応の動的計画法5分
03. 最大部分配列和 (Kadane)5分
04. 隣り合わない最大値 (House Robber)5分
05. グリッド経路数 (Unique Paths)5分
06. 単語分割可能か (Word Break)5分
07. 第6章まとめクイズ — 動的計画法 (上級)5分
7
総合データ構造と関数型
01. map と filter を組み合わせる5分
02. reduce で積を計算5分
03. 関数合成5分
04. カリー化5分
05. trie の単純検索 (prefix マッチ)5分
06. Union-Find (連結成分数)5分
07. 最終総まとめクイズ5分

グラフのパス存在判定

着いているのに、まだ歩き回っている

前の 2 つのレッスンでは、届く範囲を最後まで塗りつぶしました。今回知りたいのは 1 つだけです。「s から t へたどり着けるか」。

範囲を全部塗ってから t が入っているかを調べても答えは出ます。ただ、点が 100 万あって t が s の隣にいる場合でも、100 万点を歩き終えてから答えることになります。

t を見つけた瞬間に打ち切る。それだけで、多くの場合の探索が一瞬で終わります。

この「着けるか」は現場でもよく出てきます。この設定ファイルは間接的にでもあのモジュールを読み込んでいるか。この権限はどこかの継承をたどって管理者につながっていないか。どれも同じ問いです。

見つけたら、その場で返す

打ち切りは特別な技法ではありません。ふつうの探索でも同じことをしています。

Python

def has_admin(members): for m in members: if m["role"] == "admin": return True # 残りは見ない return False

最後まで回してから真偽値を組み立てるのではなく、条件に合ったところで return してしまう。グラフでも同じで、隣を見ている途中で t が出てきたら、キューに入れずにその場で返します。

Python

for nxt in graph[node]: if nxt == goal: return True # ここで打ち切る

判定を置く場所は 2 通りあります。キューから取り出したときに見るか、隣として見つけたときに見るか。どちらでも答えは同じですが、後者のほうが 1 歩ぶん早く終わります。

打ち切らずに最後まで回しても答えは合うので、遅いことに気づきにくいのがこの間違いの厄介なところです。

なお、この問題ではキューでもスタックでもかまいません。知りたいのは「着けるかどうか」だけで、どの順で着いたかも、何歩で着いたかも問われないからです。順番を選ぶ必要があるのは、順番そのものが答えに関わるときだけです。

再帰で書く場合は、隣に潜った結果が真なら自分も真を返す、というバケツリレーの形になります。1 つでも真が返ってきた時点で、残りの隣は見なくてよい点は同じです。

出発点と目的地が同じとき

見落としやすいのが、s と t が同じ場合です。1 歩も動かなくてよいので答えは真ですが、素直に書くと偽が返ります。

理由は順番にあります。探索を始めるとき、s を訪問済みにしてからループへ入ります。その後 s の隣を見ていっても、s 自身はすでに訪問済みなので候補に上がらず、t には二度と出会えません。

ですから、探索を始める前に「出発点と目的地が同じなら真」を先に返してしまいます。テストにもこの形が入っています。

やってみよう

  • edges=[[0,1],[1,2],[2,3]] で 0 から 3 へは真になる
  • 2 つの塊に分かれた edges=[[0,1],[2,3]] で、0 から 3 へは偽になる
  • 辺が 1 本もない状態で、出発点と目的地を同じにすると真になる
  • edges=[[0,1],[1,2],[2,0],[2,3]] のように輪を含む形でも、3 へ着けることを確かめる

要件

  1. BFS または DFS で実装すること
  2. t を見つけたら直ちに True を返して打ち切ること
  3. s == t の場合は True を返すこと

入出力例

pathExists(4, [[0,1],[1,2],[2,3]], 0, 3) → true pathExists(5, [[0,1],[2,3]], 0, 3) → false pathExists(3, [], 1, 1) → true pathExists(4, [[0,1],[1,2]], 0, 3) → false pathExists(4, [[0,1],[1,2],[2,0],[2,3]], 0, 3) → true pathExists(3, [], 0, 2) → false

ヒント

冒頭で s == t を即判定すると、辺なしグラフのテストもクリアできる

BFS の中で v == t をチェックする位置を間違えると、t を visited に入れてから判定漏れする

DFS で書くなら 'いずれかの子が True を返したら自分も True' のパターン

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • BFS で最短経路の長さを求める

    重みなし無向グラフで、BFS を使って始点から終点までの最短経路 (辺数) を求める関数を実装する。

  • トポロジカルソート

    有向非巡回グラフ (DAG) のノードを、すべての辺 u->v で u が v より前に来るように並べた配列を返す。

  • 2 部グラフ判定

    無向グラフが 2 部グラフかどうかを BFS の彩色で判定する関数を実装する。

  • ダイクストラ法 — 重み付きグラフの最短経路

    重み付きグラフでの最短経路問題を解くダイクストラ法を、概念・図・擬似コード・Python 実装・計算量・よくある誤解まで一気通貫で学ぶ。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • モジュール他ファイルから import できるPythonファイル
  • 継承親クラスの機能を子クラスへ引き継ぐ仕組み
  • グラフノード(頂点)とエッジ(辺)で構成されるデータ構造。
  • キュー先入れ先出し(FIFO)のデータ構造
  • スタック後入れ先出し(LIFO)のデータ構造
  • 再帰関数が自分自身を呼び出す処理パターン
  • ループ繰り返し処理。矢印で戻すか専用記号で示す
  • テストバグを見つける工程
main.py
学習モード
エディタを読み込んでいます

メモ

グラフのパス存在判定

⌘S で保存