diff --git a/Akash Articles/Topological-Sort.md b/Akash Articles/Topological-Sort.md new file mode 100644 index 0000000..d57a253 --- /dev/null +++ b/Akash Articles/Topological-Sort.md @@ -0,0 +1,175 @@ +## Topological Sort of Graph + +Topological Sort is the sorting of the vertices in such a way that, for any two vertices $a$ and $b$, if there is a directed edge from $a \to b$ then $a$ must appear before $b$ in the topological ordering. + +$a,b,c,d,e$ is the topologically sorted order for the graph below. + +![enter image description here](https://lh3.googleusercontent.com/zOBG-tWmznt9QeFbW-SopxIpvyDSH7RgpmYKL9fIgth_TkRQ3sfuxXsDw7iWgmmyGdqip4cay_WS) + +## Quiz Time + +Is it always possible to find out the topological sort? + +No. Whenever there is a cycle in a graph we can not find it. + +To find out the topological sort, we will use the standard graph traversal technique DFS with some modification. + +## Algorithm + + 1. Mark all the vertices as unvisited. + 2. If there is a unvisited vertex, then run the DFS starting from that vertex. Otherwise stop. + 3. Inside DFS, If all the adjacent vertices of the start vertex are visited, then prepend this vertex at the head of the linked list. + 4. Go to the step 2. + +Starting from the head, the linked list shows the topological sort of the given graph. + +**Visualization:** + + +```c++ +#include +using namespace std; +#define MAX_DIST 100000000 + +void dfs(vector > &graph, int start, list &linked_list, vector& visited) +{ + visited[start] = true; + + for(auto i: graph[start]) + if(!visited[i]) + dfs(graph, i, linked_list, visited); + + linked_list.push_front(start); + +} + +void Topological_sort(int no_vertices, vector > &graph) +{ + vector visited(no_vertices + 1); + + list linked_list; + + for(int i = 1; i <= no_vertices; i++) + if(!visited[i]) + dfs(graph, i, linked_list, visited); + + for(auto vertex: linked_list) + cout << vertex << " "; + +} + +int main() +{ + + int no_vertices = 5; + + vector > graph(no_vertices+1, vector()); + + graph[1].push_back(3); + graph[2].push_back(3); + graph[3].push_back(4); + graph[3].push_back(5); + + Topological_sort(no_vertices, graph); + + return 0; +} +``` + +## Quiz Time + +Does topological sort give a unique ordering of the vertices? + +No, it is not unique in every case, because we can find many orderings which satisfies the condition of topological sort. + +In the graph shown in the image above, $b,a,c,d,e$ and $a,b,c,d,e$ both are valid topological sorts. + +## Application + + 1. It is used to find out the shortest distance path efficiently. + 2. Scheduling of tasks according to their dependencies on each other, where dependencies are represented by the directed edges. + + +## Kahn's Algorithm for Topological Sort + +We have seen how to find the topological sort using modified DFS. Now, we will see Kahn's algorithm, which is modified BFS. + +We will use the indegree of vertices to find the next vertex of the topological ordering. How? + +**The main concept**: If the indegree of the vertex is zero, then it must appear before the vertices whose indegrees are greater than zero. + +## Algorithm + + 1. First of all, count the indegrees of all the vertices. + 2. Add all the vertices whose indegrees are zero to the queue. + 3. Start the loops like BFS. + 4. Dequeue a vertex from the queue, say V and append it to the sorting order. + 5. Visit all the adjacent vertices of V and decrease the indegrees of all of them by 1. + 6. Enqueue all the adjacent vertices whose indegrees become zero. + 7. If the queue is empty, then stop the algorithm otherwise continue from the step 4. + +**Visualization** + +```c++ +#include +using namespace std; +#define MAX_DIST 100000000 + + +void Topological_sort(int no_vertices, vector > &graph) +{ + list topological_order; + + vector indegrees(no_vertices + 1); + + for(int i = 1; i <= graph.size(); i++) + for(int j = 0; j < graph[j].size(); j++) + indegrees[graph[i][j]]++; + + + queue que; + + for(int i = 1; i <= no_vertices; i++) + if(indegrees[i] == 0) + que.push(i); + + + while(!que.empty()) + { + int V = que.front(); + que.pop(); + + topological_order.push_back(V); + + for(auto i: graph[V]) + { + --indegrees[i]; + if(indegrees[i] == 0) + que.push(i); + } + + } + + for(auto i: topological_order) + cout << i << " "; + +} + +int main() +{ + + int no_vertices = 5; + + vector > graph(no_vertices+1, vector()); + + graph[1].push_back(3); + graph[2].push_back(3); + graph[3].push_back(4); + graph[3].push_back(5); + + Topological_sort(no_vertices, graph); + + return 0; +} +``` +**Variant:** We can use the priority queue in the place of queue if we want smaller indexed vertices to appear first.