private void visit(
      Node<T> node, Set<Node<T>> unmarked, Set<Node<T>> temporarilyMarked, List<T> outList) {
    if (temporarilyMarked.contains(node)) {
      // TODO Use some GraphCycleException instead?
      throw new IllegalStateException("Graph has a cycle!");
    }
    if (!unmarked.contains(node)) {
      return;
    }
    temporarilyMarked.add(node);
    unmarked.remove(node);
    for (Node<T> toNode : node.outEdges) {
      visit(toNode, unmarked, temporarilyMarked, outList);
    }
    temporarilyMarked.remove(node);
    outList.add(0, node.data);
  }