/**
   * Perform a DFS starting on the given node and collect all nodes that are found in the
   * corresponding connected component.
   *
   * @param node a node.
   * @param graph a graph representing a connected component, or {@code null}.
   * @param visited boolean indicating for each node whether it was already visited ({@code true})
   *     or not.
   * @param incidence list of incident edges for each node.
   * @return the connected component, or {@code null} if the node was already visited.
   */
  private FGraph dfs(
      final FNode node,
      final FGraph graph,
      final boolean[] visited,
      final List<FEdge>[] incidence) {

    if (!visited[node.id]) {
      visited[node.id] = true;
      FGraph component = graph;
      if (component == null) {
        component = new FGraph();
      }
      component.getNodes().add(node);
      for (FEdge edge : incidence[node.id]) {
        if (edge.getSource() != node) {
          dfs(edge.getSource(), component, visited, incidence);
        }
        if (edge.getTarget() != node) {
          dfs(edge.getTarget(), component, visited, incidence);
        }
        component.getEdges().add(edge);
        component.getLabels().addAll(edge.getLabels());
      }
      return component;
    }
    return null;
  }
  /**
   * Creates and returns the incidence list that for each node lists the incident edges.
   *
   * @param graph a force graph.
   */
  @SuppressWarnings("unchecked")
  private List<FEdge>[] buildIncidenceLists(final FGraph graph) {
    int n = graph.getNodes().size();
    List<FEdge>[] incidence = new List[n];

    // create incidence lists
    for (FNode node : graph.getNodes()) {
      incidence[node.id] = new LinkedList<FEdge>();
    }

    // add edges to incidence lists
    for (FEdge edge : graph.getEdges()) {
      incidence[edge.getSource().id].add(edge);
      incidence[edge.getTarget().id].add(edge);
    }

    return incidence;
  }