Topological Sort
- Given a directed acyclic graph, construct an ordering of the vertices such that if there is a path from vi to vj, then vj appears after vi in the ordering
- The result is a linear list of vertices
- indegree of v: number of edges (u, v) -- meaning the number of incoming edges

Topological Sort
One valid topological sort is: v1, v6, v8, v3, v2, v7, v4, v5
What is the topological sort?
What is the topological sort?
This is already topologically sorted!
Topological sort
void Graph::topsort() {
Vertex v, w;
for (int counter=0; counter < NUM_VERTICES;
counter++) {
v = findNewVertexOfInDegreeZero();
if (v == NOT_A_VERTEX)
throw CycleFound();
v.topologicalNum = counter;
for each w adjacent to v
w.indegree--;
}
}
- What's the big-Theta running time?
- Observation: The only new (eligible) vertices with indegree 0 are the ones adjacent to the vertex just processed
Topological sort
void Graph::topsort() {
Queue q(NUM_VERTICES);
int counter = 0;
Vertex v, w;
q.makeEmpty(); // initialize the queue
for each vertex v
if (v.indegree == 0)
q.enqueue(v);
while (!q.isEmpty()) {
v = q.dequeue(); // get vertex of indegree 0
v.topologicalNum = ++counter;
for each w adjacent to v: // insert eligible verts
if (--w.indegree == 0)
q.enqueue(w);
}
if (counter != NUM_VERTICES)
throw CycleFound();
}
Another Topological Sort Example
Why do we care about shortest paths?
- The obvious answers:
- Map routing (car navigation systems, Google Maps, flights)
- 6 degrees of separation
- But what else?
- Internet routing
- Puzzle answers (Rubik's cube)
Three types of algorithms
- Single pair
- Single source
- All pairs
- We won't see this in this course
- And a variant that we'll see later:
Shortest Path Algorithms
- This version is called the "single-source" shortest path
- Given a graph G=(V,E) and a single distinguished vertex s, find the shortest weighted path from s to every other vertex in G
The weighted path length of v1,v2,…,vn:
∑n−1i=1ci,i+1 where ci,i+1 is the cost of edge (vi,vi+1)
Unweighted Shortest Path
- Special case of the weighted problem: all weights are 1
- Solution: breadth-first search; similar to level-order traversal for trees
Unweighted Shortest Path
void Graph::unweighted (Vertex s) {
Queue q(NUM_VERTICES);
Vertex v, w;
q.enqueue(s);
s.dist = 0;
while (!q.isEmpty()) {
v = q.dequeue();
for each w adjacent to v
// each edge examined at most once,
// if adjacency lists are used
if (w.dist == INFINITY) {
w.dist = v.dist + 1;
w.path = v;
q.enqueue(w); // each vertex added at most once
}
}
}
What is the big-Theta running time?
Weighted Shortest Path
- We assume no negative weight edges
- Dijkstra's algorithm: uses similar ideas as the unweighted case
- Greedy algorithms: do what seems to be best at every decision point

Dijkstra's algorithm
- Initialize each vertex's distance as infinity
- Start at a given vertex s
- Update s's distance to be 0
- Repeat
- Pick the next unknown vertex with the shortest distance to be the next v
- If no more vertices are unknown, terminate loop
- Mark v as known
- For each edge from v to adjacent unknown vertices w
- If the total distance to w is less than the current distance to w
- Update w's distance and the path to w
Dijkstra's Algorithm
V | Known? | Dist | Path |
v0 | | | |
v1 | | | |
v2 | | | |
v3 | | | |
v4 | | | |
v5 | | | |
v6 | | | |
| |  |
Dijkstra's algorithm
void Graph::dijkstra(Vertex s) {
Vertex v,w;
s.dist = 0;
while (there exist unknown vertices, find the
unknown v with the smallest distance) {
v.known = true;
for each w adjacent to v
if (!w.known)
if (v.dist + Cost_VW < w.dist) {
w.dist = v.dist + Cost_VW;
w.path = v;
}
}
}
Analysis
- How long does it take to find the smallest unknown distance?
- Simple scan using an array: Θ(v)
- Total running time:
- Using a simple scan: Θ(v2+e) = Θ(v2)
- Optimizations?
- Use adjacency lists and heaps
- Assuming that the graph is connected (i.e. e > v-1), then the running time decreases to Θ(e log v)
- Although we won't see how to do that in this course
Negative Cost Edges?
- Perhaps the graph weights are the amount of fuel expended
- Positive means fuel was used
- And passing by a fuel station is a refueling, which is a negative cost edge
- Dijkstra's algorithm does not work for negative cost edges
- What about negative cost cycles?
Shortest Path Example Problem
From the ICPC Mid-Atlantic Regionals, 2009
Minimum Spanning Tree (MST)
Spanning Tree
- Suppose you are going to build a transport system:
- Set of cities
- Roads, rail lines, air corridors connecting cities
- Trains, buses or aircraft between cities
- Which links do you actually use?
- Cannot use a complete graph
- Passengers can change at connection points
- Want to minimize number of links used
- Any solution is a tree
Spanning Tree (almost...)
Spanning Tree
- A spanning tree of a graph G is a subgraph of G that contains every vertex of G and is a tree
- Any connected graph has a spanning tree
- Any two spanning trees of a graph have the same number of nodes
- Construct a spanning tree:
- Start with the graph
- Remove an edge from each cycle
- What remains has the same set of vertices but is a tree
Spanning Trees
Original graph:
Possible spanning trees:
Minimal Spanning Tree
- Spanning trees are simple
- But suppose edges have weights!
- "Cost" associated with the edge
- Miles for a transport link, for example
- Spanning trees each have a different total weight
- Minimal-weight spanning tree: spanning tree with the minimal total weight
Minimum Spanning Trees
- Given a connected and undirected graph G = (V,E), find a graph G' = (V,E') such that:
- E' is a subset of E
- |E'| = |V| - 1
- G' is connected
- ∑(u,v)∈E′cuv is minimal
- G' is then a minimal spanning tree
- Applications: wiring a house, cable TV lines, power grids, Internet connections
Generic Minimum Spanning Tree Algorithm
- KnownVertices <- {}
- while KnownVertices does not form a spanning tree, loop:
- find edge (u,v) that is "safe" for KnownVertices
- KnownVertices <- KnownVertices U {(u,v)}
- end loop
But how to find a "safe" edge?
Prim's algorithm
Idea: Grow a tree by adding an edge to the "known" vertices from the "unknown" vertices. Pick the edge with the smallest weight.
Prim's Algorithm for MST
- Pick one node as the root,
- Incrementally add edges that connect a "new" vertex to the tree.
- Pick the edge (u,v) where:
- u is in the tree, v is not, AND
- where the edge weight is the smallest of all edges (where u is in the tree and v is not)
Prim's MST Algorithm
Edges: (v1,v2), (v1,v4), (v3,v4), (v4,v7), (v5,v7), (v6,v7)
Analysis
- Running time: Same as Dijkstra's: Θ(e log v)
- Correctness:
- Suppose we have a partially built tree that we know is contained in some minimum spanning tree T
- Let (u,v) ∈ E, where u is "known" and v is "unknown" and has minimal cost
- Then there is a MST T' that contains the partially built tree and (u,v) that has as low a cost as T
Kruskal's MST Algorithm
Idea: Grow a forest out of edges that do not create a cycle. Pick an edge with the smallest weight.
Kruskal's MST Algorithm
Edges: (v1,v4), (v6,v7), (v1,v2), (v3,v4), (v4,v7), (v5,v7)
Kruskal code
void Graph::kruskal() {
int edgesAccepted = 0;
DisjSet s(NUM_VERTICES);
while (edgesAccepted < NUM_VERTICES - 1) {
e = smallest weight edge not deleted yet;
uset = s.find(u);
vset = s.find(v);
if (uset != vset) {
edgesAccepted++;
s.unionSets(uset, vset);
}
}
}
When optimized, it has the same running time as Prim's and Dijkstra's: Θ(e log v)