Topological Sort & Shortest Paths I
Topological sort, BFS, 0-1 BFS, Dijkstra
1. Topological Sort — Order Tasks That Depend on Each Other
Given a DAG (directed acyclic graph), produce an order so that for every edge u → v, u comes before v. Used by build systems, course scheduling, package managers, etc.
2. Kahn's Algorithm — BFS on Indegrees
Compute indegree of every vertex. Push every indegree-0 vertex into a queue. Pop, output, decrement indegrees of neighbours, push any that become 0. If you can't pop V vertices, a cycle exists.
#include <bits/stdc++.h>
using namespace std;
int main() {
int V = 6;
vector<vector<int>> adj(V);
vector<int> in(V, 0);
vector<pair<int,int>> e = {{5,0},{5,2},{4,0},{4,1},{2,3},{3,1}};
for (auto [u, v] : e) { adj[u].push_back(v); in[v]++; }
queue<int> q;
for (int i = 0; i < V; i++) if (in[i] == 0) q.push(i);
vector<int> order;
while (!q.empty()) {
int u = q.front(); q.pop();
order.push_back(u);
for (int v : adj[u]) if (--in[v] == 0) q.push(v);
}
if ((int)order.size() < V) cout << "cycle\n";
else for (int u : order) cout << u << " ";
}
3. DFS-Based Topo Sort
Run DFS; when a vertex's recursion finishes, push it onto a stack. The reversed stack is a topological order. Quick and natural — but you must guarantee no cycles separately.
4. 0-1 BFS — Deque, Not Priority Queue
When edge weights are only 0 or 1, replace Dijkstra's priority queue with a deque. Push 0-weight successors to the front, 1-weight to the back. Each vertex settles in O(V + E), beating Dijkstra's O(E log V).
5. Dijkstra — Shortest Path with Non-Negative Weights
Generalises BFS to weighted graphs (no negative edges). Maintain a min-heap of (dist, vertex). Pop the smallest, relax its outgoing edges, push improved successors. Time: O((V + E) log V).
#include <bits/stdc++.h>
using namespace std;
typedef pair<long long, int> pli;
int main() {
int V = 5;
vector<vector<pair<int,int>>> adj(V); // (neighbour, weight)
vector<tuple<int,int,int>> e = {{0,1,4},{0,2,1},{2,1,2},{1,3,1},{2,3,5},{3,4,3}};
for (auto [u, v, w] : e) { adj[u].push_back({v, w}); adj[v].push_back({u, w}); }
vector<long long> dist(V, LLONG_MAX);
priority_queue<pli, vector<pli>, greater<>> pq;
dist[0] = 0; pq.push({0, 0});
while (!pq.empty()) {
auto [d, u] = pq.top(); pq.pop();
if (d > dist[u]) continue;
for (auto [v, w] : adj[u]) {
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
pq.push({dist[v], v});
}
}
}
for (int i = 0; i < V; i++)
cout << "dist[0..." << i << "] = " << dist[i] << "\n";
}
6. Practice Problems
-
Course Schedule — return any valid order of courses given prerequisite pairs.Course Schedule — Kahn's algorithm।
✨ Show Answer (উত্তর দেখুন)
Approach: Kahn's algorithm. If output size < V → cycle → return empty.
-
Network delay time — using Dijkstra to find max-of-min path from a source.Network delay time — Dijkstra।
✨ Show Answer (উত্তর দেখুন)
Approach: Dijkstra from source; answer is max(dist[i]) over all i. If any infinity remains, return -1.
-
Cheapest flights within K stops — modified Dijkstra / Bellman-Ford-lite.K stops-এর মধ্যে সবচেয়ে সস্তা ফ্লাইট।
✨ Show Answer (উত্তর দেখুন)
Approach: BFS-style relaxation for K+1 iterations (Bellman-Ford bounded). Or Dijkstra with state (city, stops_used).
-
Path with min effort on a grid — binary search + BFS, OR Dijkstra on max-edge-weight metric.Min effort path — Dijkstra (max edge weight)।
✨ Show Answer (উত্তর দেখুন)
Approach: Dijkstra where the cost of a path is the maximum edge weight encountered (not the sum). Update
dist[v] = max(dist[u], |h[v] − h[u]|). -
0-1 BFS on a grid where 0-cost moves are along free cells and 1-cost moves are crossing walls.Grid-এ 0-1 BFS।
✨ Show Answer (উত্তর দেখুন)
Approach: deque BFS; 0-edges push_front, 1-edges push_back. O(V + E).
-
Longest path in a DAG — modify topo sort.DAG-এ longest path।
✨ Show Answer (উত্তর দেখুন)
Approach: compute topological order. Process vertices in that order; for each u, for each edge u→v, do
dist[v] = max(dist[v], dist[u] + w(u,v)). O(V+E). -
Alien dictionary — given an order over a set of words, derive a valid alphabet order.Alien dictionary — char graph + topo sort।
✨ Show Answer (উত্তর দেখুন)
Approach: for each pair of consecutive words, find the first different char and add an edge. Topo-sort the char graph.
-
Why does Dijkstra need
if (d > dist[u]) continue;in the pop step?Dijkstra-তে stale pop ignore কেন?✨ Show Answer (উত্তর দেখুন)
Answer: we may push the same vertex multiple times with different (improving) distances. The first pop is the correct one; later pops carry stale distances and must be skipped, otherwise we would re-relax with worse data.
Summary — Module 27
Topological sort orders DAG vertices so every edge points forward — Kahn's (BFS) or DFS-finish-reverse. BFS gives shortest paths in unweighted graphs. 0-1 BFS uses a deque. Dijkstra with a priority queue solves shortest paths on non-negative graphs in O((V+E) log V). Negative edges? Wait for Bellman-Ford.