title | description | keywords | ||||
---|---|---|---|---|---|---|
Topological Sorting |
Topological Sorting is a linear ordering of its vertices such that for every directed edge (u, v) from vertex u to vertex v, u comes before v in the ordering. |
|
Topological Sorting is a linear ordering of its vertices such that for every directed edge
In order to find the order, we start from those nodes which do not have any prerequisites / dependencies. In other word, those nodes with indegree
The time complexity would be
The following implementation is using BFS.
G
is the graph built with the dependenciesindegree
is used to record the indegree of given nodeorders
is the topologically sorted orderisTopologicalSorted
is used to determine if the graph can be topologically sorted or not
struct TopologicalSort {
int n;
vector<int> indegree;
vector<int> orders;
vector<vector<int>> G;
bool isTopologicalSorted = false;
int steps = 0;
int nodes = 0;
TopologicalSort(vector<vector<int>>& g, vector<int>& in) {
G = g;
n = (int) G.size();
indegree = in;
int res = 0;
queue<int> q;
for(int i = 0; i < n; i++) {
if(indegree[i] == 0) {
q.push(i);
}
}
while(!q.empty()) {
int sz = q.size();
steps += 1;
nodes += q.size();
for (int i = 0; i < sz; i++) {
auto u = q.front(); q.pop();
orders.push_back(u);
for(auto v : G[u]) {
if(--indegree[v] == 0) {
q.push(v);
}
}
}
}
isTopologicalSorted = nodes == n;
}
};
Example 1: 0207 - Course Schedule
// ...
// TopologicalSort implementation here
// ...
class Solution {
public:
bool canFinish(int n, vector<vector<int>>& prerequisites) {
// define the graph
vector<vector<int>> g(n);
// define indegree
vector<int> indegree(n);
// build the graph
for(auto p : prerequisites) {
// we have to take p[1] in order to take p[0]
g[p[1]].push_back(p[0]);
// increase indegree by 1 for p[0]
indegree[p[0]]++;
}
// init topological sort
TopologicalSort ts(g, indegree);
// we can finish all courses only if we can topologically sort
return ts.isTopologicalSorted;
}
};
Example 2: 0210 - Course Schedule II
// ...
// TopologicalSort implementation here
// ...
class Solution {
public:
vector<int> findOrder(int n, vector<vector<int>>& prerequisites) {
// define the graph
vector<vector<int>> g(n);
// define indegree
vector<int> indegree(n);
// build the graph
for(auto p : prerequisites) {
// we have to take p[1] in order to take p[0]
g[p[1]].push_back(p[0]);
// increase indegree by 1 for p[0]
indegree[p[0]]++;
}
// init topological sort
TopologicalSort ts(g, indegree);
// we can finish all courses only if we can topologically sort
// hence, return an empty array if it cannot be sorted
if (!ts.isTopologicalSorted) return {};
// else return the order
return ts.orders;
}
};
Example 3: 1136. Parallel Courses
// ...
// TopologicalSort implementation here
// ...
class Solution {
public:
int minimumSemesters(int n, vector<vector<int>>& relations) {
vector<vector<int>> g(n);
vector<int> in(n);
for (auto x : relations) {
--x[0], --x[1];
g[x[0]].push_back(x[1]);
in[x[1]]++;
}
TopologicalSort ts(g, in);
return ts.isTopologicalSorted ? ts.steps : -1;
}
};