void ShGraph<G>::leastCommonAncestor(LCAMap &ancestor)
{
  typename VertexSet::const_iterator U, V, W;
  typename EdgeSet::const_iterator E;

  // First step, identify the "roots" of the DAG (those that have no
  // ancestors) 
  VertexSet roots;
  rootSet(roots);

  // Find the height of each node by longest path distance from any root
  HeightMap heights;
  vertexHeight(roots, heights);

  // Calculate the transitive closure matrix 
  TransitiveClosureMap tcm;
  transitiveClosure(tcm);

  // Identify a candidate least common ancestor (greatest height)
  // for each pair of verts 
  ancestor.clear();
  for(U = verts.begin(); U != verts.end(); ++U) {
    for(V = verts.begin(); V != verts.end(); ++V) {
      int maxHeight = -1;
      for(W = verts.begin(); W != verts.end(); ++W) {
        // if W is an ancestor of both U and V, check if its the LCA so far 
        if(tcm(*W, *U) && tcm(*W, *V) && heights[*W] > maxHeight) {
          ancestor(*U, *V) = ancestor(*V, *U) = *W;
          maxHeight = heights[*W]; 
        }
      }
    }
  }
}
int main()
{
	int m;
	scanf("%d %d",&n,&m);
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			adj[i][j] = 0;
	int u,v;
	for(int i = 0; i < m; i++)
	{
		scanf("%d %d",&u,&v);
		adj[u][v] = 1;
	}
	transitiveClosure();
	printReachabilityMatrix();
	return 0;
}