We can choose between two standard ways to represent a graph
as a collection of adjacency lists or as an adjacency matrix. Either way applies
to both directed and undirected graphs. Because the adjacency-list representation
provides a compact way to represent sparse graphs—those for which
less than V ^2—it is usually the method of choice. Most of the graph algorithms
presented in this book assume that an input graph is represented in adjacencylist
form. We may prefer an adjacency-matrix representation, however, when the
graph is dense—E is close to V^2—or when we need to be able to tell quickly
if there is an edge connecting two given vertices.
A potential disadvantage of the adjacency-list representation is that it provides
no quicker way to determine whether a given edge .u; / is present in the graph
than to search for in the adjacency list AdjOEu. An adjacency-matrix representation
of the graph remedies this disadvantage, but at the cost of using asymptotically
more memory.
the adjacency matrix A of an undirected graph is its own transpose: A = AT.
In some applications, it pays to store only the entries on and above the diagonal of
the adjacency matrix, thereby cutting the memory needed to store the graph almost
in half.