code: def top_sort(graph):
      
      order, enter, state = [], set(graph), {}
      
      def is_ready(node):
          lst = graph.get(node, ())
          if len(lst) == 0:
              return True
          for k in lst:
              sk = state.get(k, None)
              if sk == GRAY: 
                  raise ValueError("cycle")
              if sk != BLACK:
                  return False
          return True
          
      while enter:
          node = enter.pop()
          stack = []
          while True:
              state[node] = GRAY
              stack.append(node)
              for k in graph.get(node, ()):
                  sk = state.get(k, None)
                  if sk == GRAY: 
                      raise ValueError("cycle")
                  if sk == BLACK: 
                      continue
                  enter.discard(k)
                  stack.append(k)
              while stack and is_ready(stack[-1]):
                  node = stack.pop()
                  order.append(node)
                  state[node] = BLACK
              if len(stack) == 0:
                  break
              node = stack.pop()
          
      return order
docs: Time complexity is the same as DFS, which is O(V + E)
          Space complexity: O(V)