/**
  * Construct graph with a sparse adjacency representation.
  *
  * @param <V> graph node type
  * @param directed if graph is directed
  * @param adjacencies map with adjacency info
  * @return graph
  */
 public static <V> SparseGraph<V> createFromAdjacencies(
     boolean directed, Multimap<V, V> adjacencies) {
   SparseGraph<V> res = new SparseGraph<V>(directed, GraphUtils.nodes(adjacencies));
   for (Entry<V, V> en : adjacencies.entries()) {
     res.addEdge(en.getKey(), en.getValue());
   }
   res.components = new GraphComponents(res, GraphUtils.components(res.edgeTable));
   return res;
 }
 /**
  * Construct graph with specific nodes and edges.
  *
  * @param <V> graph node type
  * @param directed whether graph is directed
  * @param nodes nodes in the graph
  * @param edges edges in the graph, as ordered node pairs; each must have a 0 element and a 1
  *     element
  * @return created graph
  */
 public static <V> SparseGraph<V> createFromEdges(
     boolean directed, Iterable<V> nodes, Iterable<Edge<V>> edges) {
   SparseGraph<V> res = new SparseGraph<V>(directed, Lists.newArrayList(nodes));
   for (Edge<V> e : edges) {
     res.addEdge(e.getNode1(), e.getNode2());
   }
   res.components = new GraphComponents(res, GraphUtils.components(res.edgeTable));
   return res;
 }
 /**
  * Construct graph with specific nodes and edges
  *
  * @param <V> graph node type
  * @param directed whether graph is directed
  * @param nodes nodes in the graph
  * @param edges edges in the graph, as ordered node pairs; each must have a 0 element and a 1
  *     element
  * @return graph
  */
 public static <V> SparseGraph<V> createFromArrayEdges(
     boolean directed, Iterable<V> nodes, Iterable<V[]> edges) {
   SparseGraph<V> res = new SparseGraph<V>(directed, nodes);
   for (V[] e : edges) {
     res.addEdge(e[0], e[1]);
   }
   res.components = new GraphComponents(res, GraphUtils.components(res.edgeTable));
   return res;
 }