private static <NodeType extends IGraphNode<NodeType>> int depthFirstSearch(
      final NodeType parent,
      final NodeType rootNode,
      final HashMap<NodeType, Integer> dfnums,
      final HashMap<Integer, NodeType> vertex,
      final HashMap<NodeType, NodeType> parents,
      int dfnum) {
    parents.put(rootNode, parent);
    vertex.put(dfnum, rootNode);
    dfnums.put(rootNode, dfnum);
    dfnum++;

    final Stack<Pair<NodeType, NodeType>> nodeStack = new Stack<Pair<NodeType, NodeType>>();
    for (final NodeType child : Lists.reverse(rootNode.getChildren())) {
      nodeStack.push(new Pair<NodeType, NodeType>(child, rootNode));
    }
    while (!nodeStack.empty()) {
      final Pair<NodeType, NodeType> currentElement = nodeStack.pop();
      final NodeType currentNode = currentElement.first();
      final NodeType currentParent = currentElement.second();

      if (dfnums.get(currentNode) == -1) {
        dfnums.put(currentNode, dfnum);
        vertex.put(dfnum, currentNode);
        parents.put(currentNode, currentParent);

        dfnum++;

        for (final NodeType child : Lists.reverse(currentNode.getChildren())) {
          nodeStack.push(new Pair<NodeType, NodeType>(child, currentNode));
        }
      }
    }
    return dfnum - 1;
  }
Uses the Lengauer-Tarjan algorithm to determine the dominator tree of a directed graph.

<p>The implementation of this algorithm was taken from Modern Compiler Implementation in Java,
pages 452 and 453.
java/zylib/src/main/java/com/google/security/zynamics/zylib/types/graphs/algorithms/LengauerTarjan.java