Adjacency is an array with | V | lists, one for each
      vertex." u Î V
      Adj[u] is the adjacency list for vertex u and points to all vertices v so
      that the edge ( u, v ) Î E. If G is a directed
      graph, then:
      
        
          
            
              
                
                  
                     | 
                    
                      å 
                      u Î V  | 
                    | Adj [u] | = | E | | 
                   
                
               
             | 
          
        
      
      If G is an undirected graph, then:
      
        
           | 
          å 
            u Î V  | 
          | Adj [u] | = 2 | E | | 
        
      
       
      
 
      With the adjacency-list representation we have that:
      
         O ( max ( | V |, | E | )) = O ( | V | + | E | )
      
      memory is required. This is as small as we can imagine if G does not
      have a special (computable) structure. If G is a weighted graph then for
      each f Î E we associate wf. with
      the adjacency-list representation we merely store wf in the
      Adj[u] corresponding to v where ( u, v ) = f, the edge in question. Many
      other graph variants are easily incorporated into the adjacency-lists
      representation.
      Problem: Given edge ( u, v ) is it in the graph ?
      Answer: Must search Adj[u] to see if v is there. If Adj[u] is
      really big, this can be searching the whole graph.
      Solution: (Memory-speed trade off) Adjacency-Matrix
      representation. Assume that the vertices are numbered: 1, 2, ..., | V |.
      Associate with G the | V | x | V | matrix [A]ij = aij
      so that aij = 1 if ( i, j ) Î E and
      0 otherwise. This representation takes O (  | V |2 )
      memory whether G is sparse or dense! Clearly: ( u, v ) Î
      G ? can be answered in O ( 1 ) time!
      If G is an undirected graph, then if ( i, j ) Î Gso
      is ( j, i ) thus we have: if aij = 1, aji = 1and
      if  aij = 0 then aji = 0, so aij = aji
      . [AT]ij =  aji , AT
      is the transpose of A, swapping across a diagonal division of the matrix.
      In an undirected graph, A = AT (symmetric) instead of
      "1" in A we can use w. If 0 is a valid weight, we must identify
      non-edges with another value: "nil".
      Note: if aij = 0,1 we can store A in bit form very
      efficiently
      
      Symmetric
      
      non-symmetric or asymmetric