Advanced Graph Algorithms
Introduction
In this chapter, we explore some of the most powerful algorithms used in graphs. These algorithms allow us to solve problems like:
Finding the shortest path between nodes
Finding the minimum spanning tree
Detecting negative cycles
Finding all-pairs shortest paths
These algorithms are widely used in real-world systems such as:
Google Maps
Network routing
Recommendation engines
Traffic optimization
Telecommunication systems
1. Dijkstra’s Algorithm
Dijkstra’s algorithm finds the shortest path from a source node to all other nodes in a graph with non-negative edge weights.
Use Cases
Navigation systems
Network routing
Robot path planning
How It Works
Start at the source node
Pick the node with the smallest distance
Update distances of its neighbors
Repeat until all nodes are processed
C# Implementation
int[] Dijkstra(List<(int to, int weight)>[] graph, int source)
{
int n = graph.Length;
int[] dist = Enumerable.Repeat(int.MaxValue, n).ToArray();
dist[source] = 0;
PriorityQueue<int, int> pq = new();
pq.Enqueue(source, 0);
while (pq.Count > 0)
{
int node = pq.Dequeue();
foreach (var edge in graph[node])
{
int next = edge.to;
int weight = edge.weight;
if (dist[node] + weight < dist[next])
{
dist[next] = dist[node] + weight;
pq.Enqueue(next, dist[next]);
}
}
}
return dist;
}
Time Complexity
Using priority queue: O((V + E) log V)
2. Bellman-Ford Algorithm
Bellman-Ford is used to find the shortest paths even when negative weights exist.
Why Use Bellman-Ford?
Dijkstra fails when negative weights are present.
Bellman-Ford:
Handles negative weights
Detects negative cycles
How It Works
Repeat V-1 times:
Relax all edges
Then check for negative cycles.
C# Implementation
int[] BellmanFord(int n, List<(int u, int v, int w)> edges, int source)
{
int[] dist = Enumerable.Repeat(int.MaxValue, n).ToArray();
dist[source] = 0;
for (int i = 0; i < n - 1; i++)
{
foreach (var (u, v, w) in edges)
{
if (dist[u] != int.MaxValue && dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
}
}
}
return dist;
}
Time Complexity
O(V × E) — slower than Dijkstra
3. Floyd–Warshall Algorithm
This algorithm finds the shortest paths between all pairs of nodes.
Use Cases
Traffic systems
Routing algorithms
Distance matrix generation
How It Works
Dynamic Programming approach:
dist[i][j] = minimum distance from i to j
Update using intermediate nodes.
C# Implementation
int[,] FloydWarshall(int[,] dist, int n)
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (dist[i, k] + dist[k, j] < dist[i, j])
{
dist[i, j] = dist[i, k] + dist[k, j];
}
}
}
}
return dist;
}
Time Complexity
O(n³)
4. Minimum Spanning Tree (MST)
A Minimum Spanning Tree connects all nodes using the minimum possible total edge weight.
Two major algorithms:
Kruskal’s Algorithm
Prim’s Algorithm
Kruskal’s Algorithm
Kruskal builds the MST by selecting the smallest edges first, ensuring no cycles are formed.
Steps
Sort edges by weight
Add smallest edge that doesn't form a cycle
Use Disjoint Set (Union-Find) for cycle detection
C# Implementation (Simplified)
int Kruskal(int n, List<(int u, int v, int w)> edges)
{
edges.Sort((a, b) => a.w.CompareTo(b.w));
int total = 0;
int[] parent = Enumerable.Range(0, n).ToArray();
int Find(int x)
{
if (parent[x] == x) return x;
return parent[x] = Find(parent[x]);
}
void Union(int a, int b)
{
parent[Find(a)] = Find(b);
}
foreach (var (u, v, w) in edges)
{
if (Find(u) != Find(v))
{
Union(u, v);
total += w;
}
}
return total;
}
Time Complexity
Sorting edges: O(E log E)
Union-Find operations: almost O(1)
Prim’s Algorithm
Prim builds the MST by expanding from the starting node, always choosing the smallest edge available.
Use Cases
Dense graphs
Network cable routing
C# Implementation
int Prim(List<(int to, int weight)>[] graph)
{
int n = graph.Length;
bool[] visited = new bool[n];
PriorityQueue<(int node, int weight), int> pq = new();
pq.Enqueue((0, 0), 0);
int total = 0;
while (pq.Count > 0)
{
var (node, weight) = pq.Dequeue();
if (visited[node]) continue;
visited[node] = true;
total += weight;
foreach (var edge in graph[node])
{
if (!visited[edge.to])
{
pq.Enqueue((edge.to, edge.weight), edge.weight);
}
}
}
return total;
}
Time Complexity
O((V + E) log V) using priority queue
Summary
Advanced graph algorithms solve critical real-world problems involving optimization, shortest paths, and cost minimization.
Key Takeaways
Dijkstra ? shortest paths (no negative weights)
Bellman–Ford ? handles negative weights + detects cycles
Floyd–Warshall ? all-pairs shortest paths
Kruskal ? MST using edge sorting
Prim ? MST using greedy expansion
These algorithms are essential for interviews and system-level applications.