





from __future__ import annotations

from collections import deque
from collections.abc import Iterator
from dataclasses import dataclass





@dataclass
class       lowercase__		:
						UpperCamelCase_  =	42
						UpperCamelCase_  =	42






class       lowercase__		:


						def __init__( self			:       int					,	UpperCamelCase__			:       int		):





												'''simple docstring'''





												SCREAMING_SNAKE_CASE							:					list[list[Edge]]           =							[[] for _ in range(UpperCamelCase__		)]
												SCREAMING_SNAKE_CASE							:					Union[str, Any]           =							size


						def __getitem__( self			:       Optional[Any]					,	UpperCamelCase__			:       int		):





												'''simple docstring'''





												return iter(self._graph[vertex]		)


						@property
						def  __A ( self			:       Dict		):





												'''simple docstring'''





												return self._size


						def  __A ( self			:       Optional[Any]					,	UpperCamelCase__			:       int					,	UpperCamelCase__			:       int					,	UpperCamelCase__			:       int		):





												'''simple docstring'''





												if weight not in (0, 1):
																		raise ValueError('''Edge weight must be either 0 or 1.'''		)

												if to_vertex < 0 or to_vertex >= self.size:
																		raise ValueError('''Vertex indexes must be in [0; size).'''		)

												self._graph[from_vertex].append(Edge(UpperCamelCase__					,	UpperCamelCase__		)		)



						def  __A ( self			:       Tuple					,	UpperCamelCase__			:       int					,	UpperCamelCase__			:       int		):





												'''simple docstring'''





												SCREAMING_SNAKE_CASE							:					List[str]           =							deque([start_vertex]		)
												SCREAMING_SNAKE_CASE							:					list[int | None]           =							[None] * self.size
												SCREAMING_SNAKE_CASE							:					str           =							0

												while queue:
																		SCREAMING_SNAKE_CASE							:					Dict           =							queue.popleft()
																		SCREAMING_SNAKE_CASE							:					str           =							distances[current_vertex]
																		if current_distance is None:
																								continue

																		for edge in self[current_vertex]:
																								SCREAMING_SNAKE_CASE							:					List[str]           =							current_distance + edge.weight
																								SCREAMING_SNAKE_CASE							:					List[str]           =							distances[edge.destination_vertex]
																								if (
																								    isinstance(UpperCamelCase__					,	UpperCamelCase__		)
																								    and new_distance >= dest_vertex_distance
																								):
																														continue
																								SCREAMING_SNAKE_CASE							:					Tuple           =							new_distance
																								if edge.weight == 0:
																														queue.appendleft(edge.destination_vertex		)
																								else:
																														queue.append(edge.destination_vertex		)

												if distances[finish_vertex] is None:
																		raise ValueError('''No path from start_vertex to finish_vertex.'''		)

												return distances[finish_vertex]


if __name__ == "__main__":
					import doctest

					doctest.testmod()






from __future__ import annotations

from typing import Any





class       lowercase__		(     UpperCamelCase_):
						pass






class       lowercase__		:


						def __init__( self			:       Union[str, Any]					,	UpperCamelCase__			:       Any		):





												'''simple docstring'''





												SCREAMING_SNAKE_CASE							:					Any           =							data
												SCREAMING_SNAKE_CASE							:					Node | None           =							None


						def __iter__( self			:       Any		):





												'''simple docstring'''





												SCREAMING_SNAKE_CASE							:					List[str]           =							self
												SCREAMING_SNAKE_CASE							:					Tuple           =							[]
												while node:
																		if node in visited:
																								raise ContainsLoopError
																		visited.append(UpperCamelCase__		)
																		yield node.data
																		SCREAMING_SNAKE_CASE							:					Dict           =							node.next_node



						@property
						def  __A ( self			:       Optional[int]		):





												'''simple docstring'''





												try:
																		list(self		)
																		return False
												except ContainsLoopError:
																		return True


if __name__ == "__main__":
					__UpperCamelCase	: List[Any]    		=  Node(1)
					__UpperCamelCase	: str    		=  Node(2)
					__UpperCamelCase	: Dict    		=  Node(3)
					__UpperCamelCase	: List[Any]    		=  Node(4)
					print(root_node.has_loop)  # False
					__UpperCamelCase	: int    		=  root_node.next_node
					print(root_node.has_loop)  # True

					__UpperCamelCase	: Union[str, Any]    		=  Node(5)
					__UpperCamelCase	: Union[str, Any]    		=  Node(6)
					__UpperCamelCase	: List[Any]    		=  Node(5)
					__UpperCamelCase	: List[str]    		=  Node(6)
					print(root_node.has_loop)  # False

					__UpperCamelCase	: List[Any]    		=  Node(1)
					print(root_node.has_loop)  # False





