Overview
Terminology.
- Graph: A set of vertices (a.k.a. nodes) connected pairwise by edges.
- Vertices with an edge beteween them are adjacent.
- Path is a sequence of vertices connected by edges.
- A cycle is a path is path whose first and last vertices are the same.
- Vertices are connected if there is a path between them.
Interesting Graph Problems.
- Is there a path between s and t?
- Is there a cycle in the graph?
- Euler cycle. Is there a cycle that uses every edge exactly once?
- Hamiltonian cycle. Is there a cycle that uses every vertex exactly once?
- Planarity problem. Can the graph be drawn in the plane with no crossing edges? (See this online game for a fun (?) look at the problem.)
- Graph isomorphism. Are two graphs the same graph (but with different vertex names)
Graph Representation. There are many possible internal representations of a graph. We discussed three. You should be able to determine the runtime tradeoffs for each.
- List of edges
- Adjacency matrix
- Adjacency lists
Usually, we use the adjacency-lists representation because most real-world graphs are sparse.
Depth First Traversal. Much like we can traverse trees, we can also traverse graphs. The most natural traversal is the so called depth first traversal, represented by the following pseudocode:
dfs(s):
mark s
for each unmarked neighbor X of s:
dfs(x)
The result is that we explore the entirety of each adjacent subgraph before moving on to the next subgraph. DFS is the same thing as our depth first traversals for trees (a.k.a. preorder, inorder, and postorder). In the next lecture we'll differentiate DFS preorder vs. DFS postorder.
Paths: A Case Study. We use the Paths problem to showcase two things: decoupling and the power of DFS.
By decoupling, I mean the fact that graph algorithms are not usually included inside a Graph class itself. This is because there are just too many such algorithms that are interesting, which result in a very bloated Graph class. Instead, we usually create an object whose constructor takes a Graph object, and it does all the processing at construction time.
In the Paths problem, we create a class that supports hasPathTo() in constant time and pathTo() in time proportional to the length of the path.
In lec28, we'll discuss how this class can be implemented in some detail.
Recommended Problems
Throughout these problems, we define V as the number of vertices in a graph, and E as the number of edges.
C level
See lec28.
B level
- Why is the runtime of DFS O(V + E) time if we use an adjacency list?
- What is the runtime of DFS if we use an adjacency matrix? Give the tightest big-O bound you can.
- Adapted from Algorithm 4.10: Prove that every connected graph has a vertex whose removal (including all adjacent edges) will not disconnect the graph, and create a DFS based algorithm that finds such a vertex.
A level
- Imagine that we want to color in every node of a graph with either black or white, such that we want no node to touch any node of its same color. Prove that this is only possible if the graph contains no odd-length cycle.