A quick overview and comparison of shortest and longest path algorithms in graphs.
There are so many little points to remember about innocent looking shortest and longest path problems in graphs. Questions on this topic are very common in technical job interviews for computer programmers. However, it is often hard to keep your memory fresh and remember all details about these problems and their algorithms.
For example:
Here I provide a quick summary and important points about each of the famous algorithms in one place, which can be reviewed quickly before each interview.
Before we begin:
First, we assume the graph is G(V, E) has , where
For the shortest path problem, we assume we are after the shortest non-simple path, i.e., vertices can repeat. Also, we assume the edge weights can be an integer value, i.e., positive, negative, or zero.
The Shortest Distance problem only requires the shortest distance between nodes, whereas The Shortest Path Problem requires the actual shortest path between nodes. We discuss the shortest distance problem here. The shortest path can usually be found with minor enhancement in the algorithm.
Floyd-Warshall is the simplest algorithm:
Intuition: We calculate the shortest possible path from node i to j using nodes only from the set {1, 2, …, k} as intermediate points between them. We sweep k from 1 to n, and update d[i][j], the distance between nodes i and j:
d[i][j] = min( d[i][j], d[i][k] + d[k][j] )
Below is the implementation in C++:
Dijkstra algorithm finds the shortest path between a single source and all other nodes.
Intuition: Keep a list of visited nodes. At each step:
Below is Dijkstra’s implementation in C++:
Below is Dijkstra’s algorithm using a priority queue in C++:
This algorithm finds shortest distance from source to all other nodes.
Intuition: We have two loops:
Bellman-Ford Algorithm. Picture taken from here.
After the i-th iteration of the outer loop, the shortest paths with at most i edges are calculated. There can be maximum n - 1 edges in any simple path, so we repeat n - 1 times.
Below is an implementation of Bellman-Ford algorithm in C++.
Bellman-Ford Algorithm. Notice that we use an adjacency matrix to iterate edges
What you need to know about Bellman-Ford Algorithm
Shortest distance in a DAG (Directed Acyclic Graph) can be calculated in a linear time.
We use topological sort to find the distance of a single source to all other nodes.
Intuition: Iterate on nodes u in topological order. For each node v that is a neighbor of v, relax d[v].
What you need to know:
Below is the implementation of shortest path in DAG using topological sort:
Detailed implementation of topological sort in C++ is as follows:
Breadth First Search, BFS, can find the shortest path in a non-weighted graphs or in a weighted graph if all edges have the same non-negative weight. Without loss of generality, assume all weights are 1.
Intuition: BFS levelizes a graph, i.e., at each iteration i it visits the nodes at distance i from the source. Therefore, if the shortest path from source to a node is i, we will definitely find it in iteration i.
What you need to know about BFS:
The sister problem to finding the shortest path is to find the longest path. But first notice that there is a huge confusion when we talk about the longest path:
The longest path problem commonly means finding the longest simple path.
The shortest path problem (as discussed above), however, focuses on finding the shortest (simple or non-simple) path.
So, in the literature even when people talk about finding the longest path, they usually mean finding the longest simple path.
The longest simple path problem can be solved by converting G to -G (i.e. inverting the sign of the weight of each edge in the original G), and then calculate the shortest simple path.
Notice that if -G has no negative cycles, finding the shortest simple path is the same as finding the shortest path which can be solved in polynomial time using above algorithms.
What you need to know about the longest simple path problem
And here comes an interesting point about finding the shortest simple path in a graph that we don’t hear often:
Finding the shortest simple path in a graph is NP-hard.
This can be proved by using -G transformation to the problem of finding the longest simple path.
To understand it better, suppose there is a negative cycle in G. In this case none of our famous algorithms can find a shortest path simple because it doesn’t exit. However, there is still a shortest simple path in the graph where no vertices repeat. Finding that shortest simple path is NP-hard!
If G is a DAG, because there is no cycles, the problem of finding longest simple path can be solved using topological sort in linear time. The solution is similar to the solution for finding the shortest distance in DAGs except that we take the maximum value as we relax the distances.
Please let me know if you heard about interesting questions about shortest and longest path algorithms during job interviews. Good luck on your interview!