docs: def have_cycle(graph:dict) -> frozenset:
      """Perform a topologic sort to detect any cycle.
  
      Return the set of unsortable nodes. If at least one item,
      then there is cycle in given graph.
  
      """
      # topological sort
      walked = set()  # walked nodes
      nodes = frozenset(it.chain(it.chain.from_iterable(graph.values()), graph.keys()))  # all nodes of the graph
      preds = reversed_graph(graph)  # succ: preds
      last_walked_len = -1
      while last_walked_len != len(walked):
          last_walked_len = len(walked)
          for node in nodes - walked:
              if len(preds.get(node, set()) - walked) == 0:
                  walked.add(node)
      return frozenset(nodes - walked)