protected void compute(Node n) {
    boolean[] seen = new boolean[this.g.getMaxNodeIndex() + 1];
    int[] dist = new int[this.g.getMaxNodeIndex() + 1];
    LinkedList<Node> queue = new LinkedList<Node>();
    queue.add(n);
    seen[n.getIndex()] = true;
    dist[n.getIndex()] = 0;

    while (!queue.isEmpty()) {
      Node current = queue.pop();

      if (current instanceof DirectedNode) {
        DirectedNode curr = (DirectedNode) current;
        for (IElement out_ : curr.getOutgoingEdges()) {
          DirectedNode out = ((DirectedEdge) out_).getDst();
          if (!seen[out.getIndex()]) {
            queue.addLast(out);
            seen[out.getIndex()] = true;
            dist[out.getIndex()] = dist[curr.getIndex()] + 1;
            this.apsp.incr(dist[out.getIndex()]);
          }
        }
      } else if (current instanceof UndirectedNode) {
        UndirectedNode curr = (UndirectedNode) current;
        for (IElement out_ : curr.getEdges()) {
          UndirectedNode out = (UndirectedNode) ((UndirectedEdge) out_).getDifferingNode(curr);
          if (!seen[out.getIndex()]) {
            queue.addLast(out);
            seen[out.getIndex()] = true;
            dist[out.getIndex()] = dist[curr.getIndex()] + 1;
            this.apsp.incr(dist[out.getIndex()]);
          }
        }
      }
    }
  }
  private boolean applyBeforeUpdateDirected(Update u) {
    if (u instanceof NodeAddition) {
      Node n = (Node) ((NodeAddition) u).getNode();
      this.localCC.setValue(n.getIndex(), 0);
      this.nodePotentialCount =
          ArrayUtils.set(this.nodePotentialCount, n.getIndex(), 0, Long.MIN_VALUE);
      this.nodeTriangleCount =
          ArrayUtils.set(this.nodeTriangleCount, n.getIndex(), 0, Long.MIN_VALUE);
      this.averageCC = ArrayUtils.avgIgnoreNaN(this.localCC.getValues());
    } else if (u instanceof NodeRemoval) {

      DirectedNode n = (DirectedNode) ((NodeRemoval) u).getNode();

      DirectedNode[] neighbors = new DirectedNode[n.getNeighborCount()];
      int index = 0;
      for (IElement neighbor : n.getNeighbors()) {
        neighbors[index++] = (DirectedNode) neighbor;
      }

      for (int i = 0; i < neighbors.length; i++) {
        for (int j = i + 1; j < neighbors.length; j++) {
          if (neighbors[i].hasEdge(new DirectedEdge(neighbors[i], neighbors[j]))
              && neighbors[i].hasEdge(new DirectedEdge(neighbors[j], neighbors[i]))) {
            this.removeTriangle(n);
            this.removeTriangle(neighbors[i]);
            this.removeTriangle(neighbors[j]);
          }
        }
        this.removePotentials(neighbors[i], neighbors[i].getNeighborCount() - 1);
      }

      this.removePotentials(n, n.getNeighborCount() * (n.getNeighborCount() - 1) / 2);

      this.localCC.setValue(n.getIndex(), NodeValueList.emptyValue);
      this.nodePotentialCount[n.getIndex()] = Long.MIN_VALUE;
      this.nodeTriangleCount[n.getIndex()] = Long.MIN_VALUE;
      this.localCC.truncate();
      this.nodePotentialCount = ArrayUtils.truncate(this.nodePotentialCount, Long.MIN_VALUE);
      this.nodeTriangleCount = ArrayUtils.truncate(this.nodeTriangleCount, Long.MIN_VALUE);

      this.averageCC = ArrayUtils.avgIgnoreNaN(this.localCC.getValues());

    } else if (u instanceof EdgeAddition) {
      DirectedEdge e = (DirectedEdge) ((EdgeAddition) u).getEdge();
      DirectedNode a = e.getSrc();
      DirectedNode b = e.getDst();
      if (a.hasEdge(new DirectedEdge(b, a))) {
        // new triangles
        for (IElement cUncasted : a.getNeighbors()) {
          DirectedNode c = (DirectedNode) cUncasted;
          if (b.hasNeighbor(c)) {
            this.addTriangle(a);
            this.addTriangle(b);
            this.addTriangle(c);
          }
        }
        // new potentials
        this.addPotentials(a, a.getNeighborCount());
        this.addPotentials(b, b.getNeighborCount());
      }
    }
    return true;
  }