




# Author: OMKAR PATHAK, Nwachukwu Chidiebere

# Use a Python dictionary to construct the graph.
from __future__ import annotations

from pprint import pformat
from typing import Generic, TypeVar

SCREAMING_SNAKE_CASE__       :      Optional[int]  =   TypeVar('T')




class 		UpperCamelCase__	(Generic[T]     ):

    '''simple docstring'''



    def __init__(    self     ,  UpperCamelCase__ = True     )     ->      Union[str, Any]:
           lowerCamelCase   :      dict[T, list[T]]			 =					{}  # dictionary of lists
           lowerCamelCase   :      str			 =					directed







    def     _lowercase     (    self     ,  UpperCamelCase__     ,  UpperCamelCase__     )     ->      Any:

           if not self.directed:  # For undirected graphs
                  # if both source vertex and destination vertex are both present in the
                  # adjacency list, add destination vertex to source vertex list of adjacent
                  # vertices and add source vertex to destination vertex list of adjacent
                  # vertices.
                  if source_vertex in self.adj_list and destination_vertex in self.adj_list:
                         self.adj_list[source_vertex].append(_A     )
                         self.adj_list[destination_vertex].append(_A     )
                  # if only source vertex is present in adjacency list, add destination vertex
                  # to source vertex list of adjacent vertices, then create a new vertex with
                  # destination vertex as key and assign a list containing the source vertex
                  # as it's first adjacent vertex.
                  elif source_vertex in self.adj_list:
                         self.adj_list[source_vertex].append(_A     )
                         lowerCamelCase   :      Union[str, Any]			 =					[source_vertex]
                  # if only destination vertex is present in adjacency list, add source vertex
                  # to destination vertex list of adjacent vertices, then create a new vertex
                  # with source vertex as key and assign a list containing the source vertex
                  # as it's first adjacent vertex.
                  elif destination_vertex in self.adj_list:
                         self.adj_list[destination_vertex].append(_A     )
                         lowerCamelCase   :      Union[str, Any]			 =					[destination_vertex]
                  # if both source vertex and destination vertex are not present in adjacency
                  # list, create a new vertex with source vertex as key and assign a list
                  # containing the destination vertex as it's first adjacent vertex also
                  # create a new vertex with destination vertex as key and assign a list
                  # containing the source vertex as it's first adjacent vertex.
                  else:
                         lowerCamelCase   :      Optional[Any]			 =					[destination_vertex]
                         lowerCamelCase   :      str			 =					[source_vertex]
           else:  # For directed graphs
                  # if both source vertex and destination vertex are present in adjacency
                  # list, add destination vertex to source vertex list of adjacent vertices.
                  if source_vertex in self.adj_list and destination_vertex in self.adj_list:
                         self.adj_list[source_vertex].append(_A     )
                  # if only source vertex is present in adjacency list, add destination
                  # vertex to source vertex list of adjacent vertices and create a new vertex
                  # with destination vertex as key, which has no adjacent vertex
                  elif source_vertex in self.adj_list:
                         self.adj_list[source_vertex].append(_A     )
                         lowerCamelCase   :      List[str]			 =					[]
                  # if only destination vertex is present in adjacency list, create a new
                  # vertex with source vertex as key and assign a list containing destination
                  # vertex as first adjacent vertex
                  elif destination_vertex in self.adj_list:
                         lowerCamelCase   :      str			 =					[destination_vertex]
                  # if both source vertex and destination vertex are not present in adjacency
                  # list, create a new vertex with source vertex as key and a list containing
                  # destination vertex as it's first adjacent vertex. Then create a new vertex
                  # with destination vertex as key, which has no adjacent vertex
                  else:
                         lowerCamelCase   :      Tuple			 =					[destination_vertex]
                         lowerCamelCase   :      str			 =					[]

           return self







    def __repr__(    self     )     ->      Optional[Any]:
           return pformat(self.adj_list     )













from heapq import heappop, heappush

import numpy as np







def  _SCREAMING_SNAKE_CASE				(   a					,						a					,						a					,						a					,						)      ->      tuple[float | int, list[tuple[int, int]]]:
					__A    ,				__A	:						int       =				grid.shape
					__A	:						Any       =				[-1, 1, 0, 0]
					__A	:						Optional[Any]       =				[0, 0, -1, 1]
					if allow_diagonal:
										dx += [-1, -1, 1, 1]
										dy += [-1, 1, -1, 1]

					__A    ,				__A	:						Optional[int]       =				[(0, source)], set()
					__A	:						Any       =				np.full((rows, cols)					,						np.inf  )
					__A	:						Any       =				0
					__A	:						Any       =				np.empty((rows, cols)					,						dtype=a  )
					__A	:						Optional[Any]       =				None

					while queue:
										((__A)    ,				(__A))	:						List[str]       =				heappop(a  )
										if (x, y) in visited:
															continue
										visited.add((x, y)  )

										if (x, y) == destination:
															__A	:						int       =				[]
															while (x, y) != source:
																				path.append((x, y)  )
																				__A    ,				__A	:						Optional[int]       =				predecessors[x, y]
															path.append(a  )  # add the source manually
															path.reverse()
															return matrix[destination], path

										for i in range(len(a  )  ):
															__A    ,				__A	:						Union[str, Any]       =				x + dx[i], y + dy[i]
															if 0 <= nx < rows and 0 <= ny < cols:
																				__A	:						Optional[int]       =				grid[nx][ny]
																				if next_node == 1 and matrix[nx, ny] > dist + 1:
																									heappush(a					,						(dist + 1, (nx, ny))  )
																									__A	:						List[Any]       =				dist + 1
																									__A	:						Union[str, Any]       =				(x, y)

					return np.inf, []


if __name__ == "__main__":
				import doctest

				doctest.testmod()




