Lexicographically Smallest Topological Ordering - GeeksforGeeks

13 Jan, 2022
Given a directed graph with N vertices and M edges that may contain cycles, the task is to find the lexicographically smallest topological ordering of the graph if it exists otherwise print -1 (if the graph has cycles). Lexigraphically smallest topological ordering means that if two vertices in a graph do not have any incoming edge then the vertex with the smaller number should appear first in the ordering. For Example, in the image below many topological orderings are possible e.g 5 2 3 4 0 1, 5 0 2 4 3 1. But the smallest ordering is 4 5 0 2 3 1.Examples:  
Input:  
Output: 4 5 0 2 3 1 Even though 5 4 0 2 3 1 is also a valid topological ordering of the given graph but it is not lexicographically smallest.  
 
Approach: We will use Kahn’s algorithm for Topological Sorting with a modification. Instead of using a queue we will use a multiset to store the vertices to make sure that every time we pick a vertex it is the smallest possible of all. The overall Time complexity changes to Below is the implementation of the above approach: 
CPP
Python3
// C++ implementation of the approach#include<bits/stdc++.h>using namespace std; vector<vector<int>> adj;  // function to add edge to the graphvoid addEdge(int x,int y){    adj[x].push_back(y);} // Function to print the required topological// sort of the given graphvoid topologicalSort(){    int V = adj.size();    // Create a vector to store indegrees of all    // the vertices    // Initialize all indegrees to 0    vector<int> in_degree(V, 0);      // Traverse adjacency lists to fill indegrees of    // vertices    // This step takes O(V+E) time    for (int u = 0; u < V; u++) {        for (auto x: adj[u])            in_degree[x]++;    }      // Create a set and inserting all vertices with    // indegree 0    multiset<int> s;    for (int i = 0; i < V; i++)        if (in_degree[i] == 0)            s.insert(i);      // Initialize count of visited vertices    int cnt = 0;      // Create a vector to store result (A topological    // ordering of the vertices)    vector<int> top_order;      // One by one erase vertices from setand insert    // adjacents if indegree of adjacent becomes 0    while (!s.empty()) {          // Extract vertex with minimum number from multiset        // and add it to topological order        int u = *s.begin();        s.erase(s.begin());        top_order.push_back(u);          // Iterate through all its neighbouring nodes        // of erased node u and decrease their in-degree        // by 1        for (auto x:adj[u])              // If in-degree becomes zero, add it to queue            if (--in_degree[x] == 0)                s.insert(x);          cnt++;    }      // Check if there was a cycle    if (cnt != V) {        cout << -1;        return;    }      // Print topological order    for (int i = 0; i < top_order.size(); i++)        cout << top_order[i] << " ";}int main(){  // number of vertices  int v = 6;    // adjacency matrix  adj= vector<vector<int>>(v);   addEdge(5,2);  addEdge(5,0);  addEdge(4,0);  addEdge(4,1);  addEdge(2,3);  addEdge(3,1);     // find required topological order  topologicalSort();}
# Python3 implementation of the approachimport heapq as hq   # function to add edge to the graphdef addEdge(x, y):    adj[x].append(y)  # Function to print required topological# sort of the given graphdef topologicalSort():    V = len(adj)    # Create a vector to store indegrees of all    # the vertices    # Initialize all indegrees to 0    in_degree = [0] * V     # Traverse adjacency lists to fill indegrees of    # vertices    # This step takes O(V+E) time    for u in range(V):        for x in adj[u]:            in_degree[x] += 1    # Create a heap and inserting all vertices with    # indegree 0    s = []    for i in range(V):        if in_degree[i] == 0:            hq.heappush(s, i)     # Initialize count of visited vertices    cnt = 0     # Create a vector to store result (A topological    # ordering of the vertices)    top_order = []     # One by one erase vertices from setand insert    # adjacents if indegree of adjacent becomes 0    while s:         # Extract vertex with minimum number from multiset        # and add it to topological order        u = hq.heappop(s)        top_order.append(u)         # Iterate through all its neighbouring nodes        # of erased node u and decrease their in-degree        # by 1        for x in adj[u]:            in_degree[x] -= 1            # If in-degree becomes zero, add it to queue            if in_degree[x] == 0:                hq.heappush(s, x)         cnt += 1     # Check if there was a cycle    if cnt != V:        print(-1)        return     # Print topological order    for i in range(len(top_order)):        print(top_order[i], end=" ")  if __name__ == "__main__":    # number of vertices    v = 6     # adjacency matrix    adj = [[] for _ in range(v)]     addEdge(5, 2)    addEdge(5, 0)    addEdge(4, 0)    addEdge(4, 1)    addEdge(2, 3)    addEdge(3, 1)     # find required topological order    topologicalSort()
4 5 0 2 3 1
 
Time Complexity: O(N)Auxiliary Space: O(N)
pankajsharmagfg
ashutoshsinghgeeksforgeeks
amartyaghoshgfg
khushboogoyal499
Topological Sorting
Algorithms
Binary Search Tree
Competitive Programming
Graph
Graph
Binary Search Tree
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
SDE SHEET - A Complete Guide for SDE Preparation
DSA Sheet by Love Babbar
Introduction to Algorithms
How to write a Pseudo Code?
Difference between Informed and Uninformed Search in AI
Binary Search Tree | Set 1 (Search and Insertion)
AVL Tree | Set 1 (Insertion)
Binary Search Tree | Set 2 (Delete)
A program to check if a binary tree is BST or not
Construct BST from given preorder traversal | Set 1