Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonですべてのコースを受講できるかどうかを判定するプログラム

2次元の行列が与えられ、matrix[i] にはコース i を受講するために必要な前提コース(履修条件)のリストが格納されているものとします。このとき、すべてのコースを受講することが可能かどうかを判定する必要があります。

例えば、入力が matrix = [[1],[2],[]] の場合、出力は True になります。これは、コース 2 → コース 1 → コース 0 の順番で受講できるためです。

この問題は、前提関係を有向グラフとみなし、深さ優先探索(DFS)によってサイクル(循環参照)が存在しないかを確認することで解けます。前提コース同士が循環していると、その環状の中にあるコースはどれも受講できず、結果としてすべてのコースの修了は不可能になります。

アルゴリズムの手順

まず、dfs(i) という関数を定義します。この関数は次のように動作します。

  • vis[i] が True の場合(現在の探索経路上で既に訪問済み=サイクルを検出)、False を返します。
  • chk[i] が True の場合(過去の探索で問題ないことが確認済み)、True を返します。
  • vis[i] := True と設定します。
  • matrix[i] 内の各要素 j について、dfs(j) が False を返したら、False を返します。
  • vis[i] := False に戻し(バックトラック)、chk[i] := True として True を返します。

続いて、メイン処理では以下を行います。

  • vis:matrix の行数と同じサイズのリストで、初期値はすべて False。現在の探索パス上の訪問状態を管理します。
  • chk:matrix の行数と同じサイズのリストで、初期値はすべて False。一度確認が完了したノードを記録し、再計算を避けるメモ化の役割を果たします。
  • i を 0 から matrix の行数まで順にループし、dfs(i) が False を返したら False を返します。
  • すべての i で dfs(i) が成功すれば、True を返します。

それでは、理解を深めるために実際の実装を見てみましょう。

実装例

class Solution:
   def solve(self, matrix):
      vis=[False for _ in matrix]
      chk=[False for _ in matrix]
      def dfs(i):
         if vis[i]: return False
         if chk[i]: return True
         vis[i]=True
         for j in matrix[i]:
            if not dfs(j):
               return False
         vis[i]=False
         chk[i]=True
         return True
   for i in range(len(matrix)):
      if not dfs(i):
         return False
   return True
ob = Solution()
matrix = [ [1], [2], [] ]
print(ob.solve(matrix))

入力

matrix = [
   [1],
   [2],
   []
]

出力

True

このように、vis 配列で現在の探索経路を追跡しながらサイクルを検出し、chk 配列で確認済みのノードを記録することで、効率よくすべてのコースが受講可能かどうかを判定できます。計算量は O(V + E)(V はコース数、E は前提関係の数)となり、大規模なデータにも対応できます。

  1. Pythonでグラフに奇数長の閉路(サイクル)が存在するか判定するプログラム

    問題概要無向グラフが与えられたとき、そのグラフの中に奇数長の閉路(サイクル)が存在するかどうかを判定します。例えば、次のような隣接リストが入力として与えられたとします。adj_list = [[1, 2], [0, 3, 4], [0, 3, 4], [1, 2, 4], [1, 2, 3]]この場合、[0, 1, 3, 4, 2]、[1, 3, 4]、[2, 3, 4] のような奇数個の頂点からなる閉路が存在するため、出力は True になります。アルゴリズム(DFSによる解法)この問題は深さ優先探索(DFS)を用いて効率的に解けます。ポイントは、現在探索中のパス上で各ノードの位置(インデッ

  2. Pythonで与えられたグラフが2部グラフかどうかを判定するプログラム

    2部グラフとは無向グラフが与えられたとき、そのグラフが2部グラフ(バイパータイトグラフ)であるかどうかを判定する方法を解説します。2部グラフとは、グラフのすべての頂点を2つの集合 A と B に分割でき、グラフ内のすべての辺 {u, v} が必ず一方の端点 u が集合 A、もう一方の端点 v が集合 B に属するようなグラフのことです。つまり、同じ集合内の頂点同士を結ぶ辺(A-A や B-B)が一切存在しないグラフです。例として、次のようなグラフを考えてみましょう。この場合、頂点 [0, 4] を集合 A に、[1, 2, 3] を集合 B に分類できます。すべての辺は A から B、または