'''simple docstring'''






from __future__ import annotations

from collections.abc import Callable
from typing import Generic, TypeVar

__a									=   TypeVar('T')
__a									=   TypeVar('U')





class        A__				(			Generic[T, U]  ):





   """simple docstring"""





   def __init__(					self	:						str		,	lowerCAmelCase__	:						Union[str, Any]		,	lowerCAmelCase__	:						Union[str, Any]     )			->       Optional[int]:







      """simple docstring"""




      _UpperCAmelCase				:      str				=  key
      _UpperCAmelCase				:      Tuple				=  val
      _UpperCAmelCase				:      DoubleLinkedListNode[T, U] | None				=  None
      _UpperCAmelCase				:      DoubleLinkedListNode[T, U] | None				=  None




   def __repr__(					self	:						int     )			->       int:







      """simple docstring"""




      return (
          F"""Node: key: {self.key}, val: {self.val}, """
          F"""has next: {bool(self.next     )}, has prev: {bool(self.prev     )}"""
      )





class        A__				(			Generic[T, U]  ):





   """simple docstring"""





   def __init__(					self	:						str     )			->       Optional[int]:







      """simple docstring"""




      _UpperCAmelCase				:      DoubleLinkedListNode[T, U]				=  DoubleLinkedListNode(A_		,	A_     )
      _UpperCAmelCase				:      DoubleLinkedListNode[T, U]				=  DoubleLinkedListNode(A_		,	A_     )
      _UpperCAmelCase				:      Any				=  self.rear, self.head




   def __repr__(					self	:						Union[str, Any]     )			->       List[Any]:







      """simple docstring"""




      _UpperCAmelCase				:      Union[str, Any]				=  ["""DoubleLinkedList"""]
      _UpperCAmelCase				:      List[str]				=  self.head
      while node.next is not None:
         rep.append(str(A_     )     )
         _UpperCAmelCase				:      List[str]				=  node.next
      rep.append(str(self.rear     )     )
      return ",\n    ".join(A_     )




   def      _lowerCAmelCase						(					self	:						Optional[int]		,	lowerCAmelCase__	:						List[Any]     )			->       List[Any]:







      """simple docstring"""




      _UpperCAmelCase				:      Optional[int]				=  self.rear.prev

      # All nodes other than self.head are guaranteed to have non-None previous
      assert previous is not None

      _UpperCAmelCase				:      Any				=  node
      _UpperCAmelCase				:      List[Any]				=  previous
      _UpperCAmelCase				:      Dict				=  node
      _UpperCAmelCase				:      List[Any]				=  self.rear




   def      _lowerCAmelCase						(					self	:						Dict		,	lowerCAmelCase__	:						str     )			->       Dict:







      """simple docstring"""




      if node.prev is None or node.next is None:
         return None

      _UpperCAmelCase				:      Dict				=  node.next
      _UpperCAmelCase				:      Tuple				=  node.prev
      _UpperCAmelCase				:      Tuple				=  None
      _UpperCAmelCase				:      Optional[Any]				=  None
      return node





class        A__				(			Generic[T, U]  ):





   """simple docstring"""





   UpperCamelCase_			:		Dict       							=	{}




   def __init__(					self	:						Tuple		,	lowerCAmelCase__	:						Any     )			->       List[str]:







      """simple docstring"""




      _UpperCAmelCase				:      DoubleLinkedList[T, U]				=  DoubleLinkedList()
      _UpperCAmelCase				:      List[str]				=  capacity
      _UpperCAmelCase				:      Optional[Any]				=  0
      _UpperCAmelCase				:      Any				=  0
      _UpperCAmelCase				:      Union[str, Any]				=  0
      _UpperCAmelCase				:      dict[T, DoubleLinkedListNode[T, U]]				=  {}




   def __repr__(					self	:						str     )			->       Dict:







      """simple docstring"""




      return (
          F"""CacheInfo(hits={self.hits}, misses={self.miss}, """
          F"""capacity={self.capacity}, current size={self.num_keys})"""
      )




   def __contains__(					self	:						int		,	lowerCAmelCase__	:						List[str]     )			->       Optional[int]:







      """simple docstring"""




      return key in self.cache




   def      _lowerCAmelCase						(					self	:						Union[str, Any]		,	lowerCAmelCase__	:						Any     )			->       int:







      """simple docstring"""




      if key in self.cache:
         self.hits += 1
         _UpperCAmelCase				:      DoubleLinkedListNode[T, U]				=  self.cache[key]
         _UpperCAmelCase				:      List[Any]				=  self.list.remove(self.cache[key]     )
         assert node == value_node

         # node is guaranteed not None because it is in self.cache
         assert node is not None
         self.list.add(A_     )
         return node.val
      self.miss += 1
      return None




   def      _lowerCAmelCase						(					self	:						Dict		,	lowerCAmelCase__	:						Optional[Any]		,	lowerCAmelCase__	:						Optional[int]     )			->       Dict:







      """simple docstring"""




      if key not in self.cache:
         if self.num_keys >= self.capacity:
            # delete first node (oldest) when over capacity
            _UpperCAmelCase				:      Optional[int]				=  self.list.head.next

            # guaranteed to have a non-None first node when num_keys > 0
            # explain to type checker via assertions
            assert first_node is not None
            assert first_node.key is not None
            assert (
                self.list.remove(A_     ) is not None
            )  # node guaranteed to be in list assert node.key is not None

            del self.cache[first_node.key]
            self.num_keys -= 1
         _UpperCAmelCase				:      List[str]				=  DoubleLinkedListNode(A_		,	A_     )
         self.list.add(self.cache[key]     )
         self.num_keys += 1

      else:
         # bump node to the end of the list, update value
         _UpperCAmelCase				:      Tuple				=  self.list.remove(self.cache[key]     )
         assert node is not None  # node guaranteed to be in list
         _UpperCAmelCase				:      Optional[int]				=  value
         self.list.add(A_     )




   @classmethod
   def      _lowerCAmelCase						(					cls	:						str		,	lowerCAmelCase__	:						int = 1_2_8     )			->       Dict:







      """simple docstring"""




      def cache_decorator_inner(lowerCAmelCase__	:						Optional[Any]     ) -> Callable[..., U]:
         def cache_decorator_wrapper(*lowerCAmelCase__	:						int     ) -> U:
            if func not in cls.decorator_function_to_instance_map:
               _UpperCAmelCase				:      Optional[int]				=  LRUCache(A_     )

            _UpperCAmelCase				:      List[str]				=  cls.decorator_function_to_instance_map[func].get(args[0]     )
            if result is None:
               _UpperCAmelCase				:      str				=  func(*A_     )
               cls.decorator_function_to_instance_map[func].put(args[0]		,	A_     )
            return result

         def cache_info() -> LRUCache[T, U]:
            return cls.decorator_function_to_instance_map[func]

         setattr(A_		,	"cache_info"		,	A_     )  # noqa: B010

         return cache_decorator_wrapper

      return cache_decorator_inner


if __name__ == "__main__":
     import doctest

     doctest.testmod()



# A Bipartite Graph is a graph whose vertices can be divided into two independent sets,
# U and V such that every edge (u, v) either connects a vertex from U to V or a vertex
# from V to U. In other words, for every edge (u, v), either u belongs to U and v to V,
# or u belongs to V and v to U. We can also say that there is no edge that connects
# vertices of same set.




def    a__    (		snake_case__					:							Dict     ):
  _UpperCAmelCase		:							str							=     [False] * len(snake_case__     )
  _UpperCAmelCase		:							str							=     [-1] * len(snake_case__     )

  def dfs(snake_case__					:							Dict						,   snake_case__					:							Optional[Any]     ):
    _UpperCAmelCase		:							str							=     True
    _UpperCAmelCase		:							Optional[Any]							=     c
    for u in graph[v]:
      if not visited[u]:
        dfs(snake_case__						,   1 - c     )

  for i in range(len(snake_case__     )     ):
    if not visited[i]:
      dfs(snake_case__						,   0     )

  for i in range(len(snake_case__     )     ):
    for j in graph[i]:
      if color[i] == color[j]:
        return False

  return True


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





print(check_bipartite_dfs(graph))





