private void build(ObjIntConsumer<? super Node> putTNumber,
                       ObjIntConsumer<? super Node> putNNumber,
                       Node[] allNodes) {
      for (int i = 0; i < index.length; i++) {
        if (index[i] != -1) {
          continue;
        }

        frames.addLast(new TarjanFrame<>(i, allNodes, buildOuts(allNodes[i])));
        List<List<Node>> sccs = new ArrayList<>();

        strongConnect(sccs, allNodes);

        for (List<Node> scc : sccs) {
          int sccSize = scc.size();

          mySCCs.add(sccSize);
          int sccBase = index.length - sccsSizeCombined - sccSize;

          // root node should be first in scc for some reason
          Node rootNode = allNodes[i];
          int rIndex = scc.indexOf(rootNode);
          if (rIndex != -1) {
            Node e1 = scc.get(rIndex);
            Node e2 = scc.get(0);
            scc.set(rIndex, e2);
            scc.set(0, e1);
          }

          for (int j = 0; j < scc.size(); j++) {
            Node sccNode = scc.get(j);
            int tIndex = sccBase + j;
            myInvT[tIndex] = sccNode;
            putTNumber.accept(sccNode, tIndex);
          }
          sccsSizeCombined += sccSize;
        }
      }

      for (int i = 0; i < topo.size(); i++) {
        int nodeI = topo.getInt(i);
        Node node = allNodes[nodeI];

        putNNumber.accept(node, index.length - 1 - i);
        myInvN[index.length - 1 - i] = node;
      }

      // have to place SCCs in topological order too
      for (int i = 0, j = mySCCs.size() - 1; i < j; i++, j--) {
        int tmp = mySCCs.getInt(i);
        mySCCs.set(i, mySCCs.getInt(j));
        mySCCs.set(j, tmp);
      }
    }
private void build(ObjIntConsumer<? super Node> putTNumber,
                       ObjIntConsumer<? super Node> putNNumber,
                       Node[] allNodes)