Data Structures, Algorithms, & Applications in Java
Chapter 17, Exercise 35

First we input the number of vertices and edges in the new digraph; verify that these numbers are legitimate (i.e., neither is less than zero and the number of edges does not exceed the number of edges in a complete digraph with the given number of vertices); allocate an array h of the needed size; and finally read in the edges one by one. If each edge is added to the data structure being constructed using the method putEdge as we did in Exercise 31 for the establishment of an adjacency matrix structure, the time complexity becomes O(ne) because it takes O(n) time to verify that each edge is not already in the digraph.

We can reduce the complexity to O(n+e)) by deferring the check for duplicate edges to the end. Once the edges have been input, we can scan the adjacency list for each vertex using an array seen[0:n]. Initially, seen[v] is false for every vertex v. If vertex v is encountered on the adjacency list for vertex i, we first check to see if seen[v] is true. If it is, then we are seeing v for the second time on the adjacency list for vertex i. Therefore, we have found a duplicate edge and we throw a MyInputException exception. If seen[v] is false, then we are seeing v for the first time and we set seen[v] to true.

The code is given below.
public class ExtendedLinkedWDigraph extends LinkedWDigraph
{
   // constructors
   public ExtendedLinkedWDigraph(int theVertices)
      {super(theVertices);}
   
   // default is a 0 vertex graph
   public ExtendedLinkedWDigraph()
      {super(0);}

   /** put edge e into the digraph, do not check if it is a duplicate */
   public void putEdgeNoCheck(Object theEdge)
   {
      WeightedEdge edge =  (WeightedEdge) theEdge;
      int v1 = edge.vertex1;
      int v2 = edge.vertex2;
      if (v1 < 1 || v2 < 1 || v1 > n || v2 > n || v1 == v2)
         throw new IllegalArgumentException
                   ("(" + v1 + "," + v2 + ") is not a permissible edge");

      // put v2 at front of chain aList[v1]
      aList[v1].add(0, new WeightedEdgeNode(v2, edge.weight));
      e++;
   }
   
   /** input a weighted digraph and store as this
     * @param inputMethod input method to use
     * @param inStream input stream for input */
   public void input(Method inputMethod, MyInputStream inStream)
   {
      // input number of vertices and edges
      System.out.println("Enter the number of vertices in the digraph");
      n = inStream.readInteger();
      if (n < 0)
         throw new MyInputException
                   ("number of vertices must be >= 0");

      System.out.println("Enter the number of edges in the digraph");
      int numOfEdges = inStream.readInteger();
      if (numOfEdges < 0)
         throw new MyInputException
                   ("number of edges must be >= 0");

      if (numOfEdges > n * (n - 1))
         throw new MyInputException("too many edges");

      // create a new array aList for the adjacency chains
      aList = new GraphChain [n + 1];
      for (int i = 1; i <= n; i++)
         aList[i] = new GraphChain();
      e = 0;    // reset current number of edges to zero
   
      // now input the edges and add them to a[][]
      WeightedEdge newEdge = new WeightedEdge(0, 0, null);
      Object [] inputMethodArgs = {inStream};
      for (int i = 1; i <= numOfEdges; i++)
      {
         System.out.println("Enter edge " + i);
         newEdge.vertex1 = inStream.readInteger();
         newEdge.vertex2 = inStream.readInteger();
         try
         {
            newEdge.weight = 
               (Operable) inputMethod.invoke(null, inputMethodArgs);
         }
         catch (Exception e)
         {
            throw new IllegalArgumentException
                      ("static method input() not defined");
         }
         putEdgeNoCheck(newEdge);
      }

      // check for duplicate edges
      boolean [] seen = new boolean [n + 1];
      for (int i = 1; i <= n; i++)
      {// check vertex i
         Iterator ig = iterator(i);
         while (ig.hasNext())
         {// not at list end 
            int v = ((WeightedEdgeNode) ig.next()).vertex;
            if (seen[v])
               // duplicate edge
               throw new MyInputException
                         ("Duplicate edges encountered in input");
            else seen[v] = true;
         }
   
         // reset seen
         ig = iterator(i);  
         while (ig.hasNext())
            // not at list end 
            seen[((WeightedEdgeNode) ig.next()).vertex] = false;
      }
   }
}