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.

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)