


SCREAMING_SNAKE_CASE__					:     Tuple       =     {
    'A': ['B', 'C', 'E'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F', 'G'],
    'D': ['B'],
    'E': ['A', 'B', 'D'],
    'F': ['C'],
    'G': ['C'],
}




def    a__    (		snake_case__					:							dict						,   snake_case__					:							int						,   snake_case__					:							Optional[int]     ):
  _UpperCAmelCase		:							Any							=     set()
  # keep track of all the paths to be checked
  _UpperCAmelCase		:							List[Any]							=     [[start]]

  # return path if start is goal
  if start == goal:
    return [start]

  # keeps looping until all possible paths have been checked
  while queue:
    # pop the first path from the queue
    _UpperCAmelCase		:							List[str]							=     queue.pop(0     )
    # get the last node from the path
    _UpperCAmelCase		:							str							=     path[-1]
    if node not in explored:
      _UpperCAmelCase		:							Dict							=     graph[node]
      # go through all neighbour nodes, construct a new path and
      # push it into the queue
      for neighbour in neighbours:
        _UpperCAmelCase		:							List[Any]							=     list(snake_case__     )
        new_path.append(snake_case__     )
        queue.append(snake_case__     )
        # return path if neighbour is goal
        if neighbour == goal:
          return new_path

            # mark node as explored
      explored.add(snake_case__     )

    # in case there's no path between the 2 nodes
  return []




def    a__    (		snake_case__					:							dict						,   snake_case__					:							List[Any]						,   snake_case__					:							Dict     ):
  if not graph or start not in graph or target not in graph:
    return -1
  if start == target:
    return 0
  _UpperCAmelCase		:							Union[str, Any]							=     [start]
  _UpperCAmelCase		:							Dict							=     set(snake_case__     )
  # Keep tab on distances from `start` node.
  _UpperCAmelCase		:							Union[str, Any]							=     {start: 0, target: -1}
  while queue:
    _UpperCAmelCase		:							Any							=     queue.pop(0     )
    if node == target:
      _UpperCAmelCase		:							int							=     (
          dist[node] if dist[target] == -1 else min(dist[target]						,   dist[node]     )
      )
    for adjacent in graph[node]:
      if adjacent not in visited:
        visited.add(snake_case__     )
        queue.append(snake_case__     )
        _UpperCAmelCase		:							Tuple							=     dist[node] + 1
  return dist[target]


if __name__ == "__main__":
 print(bfs_shortest_path(demo_graph, 'G', 'D'))  # returns ['G', 'C', 'A', 'B', 'D']
 print(bfs_shortest_path_distance(demo_graph, 'G', 'D'))  # returns 4









def    a__    (		snake_case__					:							Tuple     ):  # noqa: E741
  _UpperCAmelCase		:							Dict							=     len(snake_case__     )
  _UpperCAmelCase		:							Tuple							=     0
  _UpperCAmelCase		:							Union[str, Any]							=     [0] * n
  _UpperCAmelCase		:							Union[str, Any]							=     [False] * n
  _UpperCAmelCase		:							Tuple							=     [False] * n

  def dfs(snake_case__					:							List[str]						,   snake_case__					:							int						,   snake_case__					:							str						,   snake_case__					:							int     ):
    if parent == root:
      out_edge_count += 1
    _UpperCAmelCase		:							List[Any]							=     True
    _UpperCAmelCase		:							List[str]							=     at

    for to in l[at]:
      if to == parent:
        pass
      elif not visited[to]:
        _UpperCAmelCase		:							Optional[Any]							=     dfs(snake_case__						,   snake_case__						,   snake_case__						,   snake_case__     )
        _UpperCAmelCase		:							Optional[Any]							=     min(low[at]						,   low[to]     )

        # AP found via bridge
        if at < low[to]:
          _UpperCAmelCase		:							List[str]							=     True
        # AP found via cycle
        if at == low[to]:
          _UpperCAmelCase		:							Optional[Any]							=     True
      else:
        _UpperCAmelCase		:							str							=     min(low[at]						,   snake_case__     )
    return out_edge_count

  for i in range(snake_case__     ):
    if not visited[i]:
      _UpperCAmelCase		:							List[Any]							=     0
      _UpperCAmelCase		:							List[str]							=     dfs(snake_case__						,   snake_case__						,   -1						,   snake_case__     )
      _UpperCAmelCase		:							Optional[Any]							=     out_edge_count > 1

  for x in range(len(snake_case__     )     ):
    if is_art[x] is True:
      print(snake_case__     )


# Adjacency list of graph
SCREAMING_SNAKE_CASE__					:     Optional[Any]       =     {
    0: [1, 2],
    1: [0, 2],
    2: [0, 1, 3, 5],
    3: [2, 4],
    4: [3],
    5: [2, 6, 8],
    6: [5, 7],
    7: [6, 8],
    8: [5, 7],
}





compute_ap(data)





