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

We can compute row tc[i][*] for any i by performing a depth-first or breadth-first search starting at vertex i. All vertices j reached during this process have tc[i][j] = 1.

The code is given below. Note that this code does not set tc[i][i] correctly when the graph is undirected (but then, it is not intended for use with an undirected graph). A test program, input, and output appear in the files TestDirectedTransitiveClosure.
// class data members of Graph
static int [][] tc;       // transitive closure array
static int theRow;        // row of tc that is being computed

/** @return the transitive closure of a directed graph */
public int [][] directedTC()
{
   int n = vertices();
   reach = new int [n + 1];

   // create transitive closure array, default initial values are 0
   tc = new int [n + 1][n + 1];

   // compute tc row by row using depth first search
   for (theRow = 1; theRow <= n; theRow++)
   {
      // initialize reach
      for (int j = 1; j <= n; j++)
         reach[j] = 0;

      // set row i of tc
      tcRow(theRow);
   }
   return tc;
}

/** set row theRow of transitive closure array tc
  * @param v is vertex for depth first search */
void tcRow(int v)
{
   reach[v] = 1;
   Iterator iv = iterator(v);
   while (iv.hasNext())
   {// visit an adjacent vertex of v
      int u = ((EdgeNode) iv.next()).vertex; 
      if (reach[u] == 0)  
      {// u is an unreached vertex
         tc[theRow][u] = 1;
         tcRow(u);
      }
      else
         // u is reachable from theRow, need next line to catch tc[u][u]
         tc[theRow][u] = 1;
   }
}



It takes Theta(n2) time to create the array tc. Each invocation of tcRow takes O(n2) when adjacency matrices are used and O(n+e) time if adjacency lists are used. The overall complexity is O(n3) when adjacency matrices are used and O(n(n+e)) when adjacency lists are used.