From 3a861097ebe9797305c6eebdf024e0d625d0e2b0 Mon Sep 17 00:00:00 2001 From: Akash Kumar Bhagat Date: Thu, 17 Dec 2020 23:58:06 +0530 Subject: [PATCH 1/4] SCC_Kosaraju's Added --- Python/graphs/SCC_Kosaraju.py | 106 ++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 Python/graphs/SCC_Kosaraju.py diff --git a/Python/graphs/SCC_Kosaraju.py b/Python/graphs/SCC_Kosaraju.py new file mode 100644 index 0000000000..1bbfc99cdf --- /dev/null +++ b/Python/graphs/SCC_Kosaraju.py @@ -0,0 +1,106 @@ +""" +Strongly Connected Components : A directed graph is strongly connected + if there is a path between all pairs of vertices. A strongly + connected component (SCC) of a directed graph is a maximal + strongly connected subgraph. + +Purpose: To find all the Strongly Connected Components (SCC) in the + given directed graph. + +Method: Kosaraju's Algorithms / Double DFS +Intution: We can find all strongly connected components in O(N+M) time + using Kosaraju’s algorithm. Following is detailed Kosaraju’s algorithm. + + 1) Create an empty stack ‘S’ and do DFS traversal of a graph. + In DFS traversal, after calling recursive DFS for adjacent + vertices of a vertex, push the vertex to stack. + 2) Reverse directions of all arcs to obtain the transpose graph. + 3) One by one pop a vertex from S while S is not empty. Let the + popped vertex be ‘v’. Take v as source and do DFS (call DFSU(node)). + The DFS starting from v prints strongly connected component of v. + +Time Complexity: O(N+M) +Space Complexity: O(N) + +Argument: Dictionary ( Graph with each node numbered from 1 to N) +Return : List ( List of diffrent Strongly Connected Components) + +""" +from collections import defaultdict + +def DFS(graph,node,visited,stack,display): + + # Mark the node Visited + visited[node]=True + + for i in graph[node]: + + # Recursively call all DFS() function to all its unvisited adjacent nodes + if not visited[i]: + DFS(graph,i,visited,stack,display) + + # If the display is True, then Display the SCC + if display: + print(node,end=" ") + else: + stack.append(node) + +# Reverse_Graph() function reverse all the directed edges of the graph +def Reverse_Graph(graph): + + rev_graph=defaultdict(list) + for i in graph.keys(): + for j in graph[i]: + rev_graph[j].append(i) + + # Return the reversed graph + return rev_graph + +def SCC_Kosaraju(n,graph): + + # Initilize the Stack + stack=[] + + # To keep a track of all the visited nodes + visited=[False]*(n+1) + + for i in range(1,n+1): + + # (1) Recursively call DFS() to push the unvisited nodes into the stack + if not visited[i]: + DFS(graph,i,visited,stack,False) + + # (2) Reverse the Graph + rev_graph=Reverse_Graph(graph) + + # Mark all the nodes Unvisited + visited=[False]*(n+1) + + while stack: + node=stack.pop() + + # For each unvisited node in the stack, call DFS() + if not visited[node]: + + # Print the SCC in formated way + print("[ ",end="") + DFS(rev_graph,node,visited,stack,True) + print("]") + + +if __name__ == "__main__": + + n, m = map(int, input("Enter the number of vertex and edges: ").split()) + print("Enter the edges: ") + + # Store the graph in the form of Dictionary + graph = defaultdict(list) + + for i in range(m): + a, b = map(int, input().split()) + # Directed Graph + graph[a] += [b] + + print("The Strongly Connected Componentes in the given Directed Graph are :") + SCC_Kosaraju(n, graph) + From 9e0e609531012d0b9bc17d70dadffe94826b7d7b Mon Sep 17 00:00:00 2001 From: Akash Kumar Bhagat Date: Thu, 17 Dec 2020 23:59:18 +0530 Subject: [PATCH 2/4] README.md updated --- Python/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/README.md b/Python/README.md index 6bf01ee6e8..316ebb5026 100644 --- a/Python/README.md +++ b/Python/README.md @@ -135,6 +135,7 @@ - [Topological Sort/Ordering](graphs/Topological_Sort.py) - [Hamiltonian Path](graphs/Hamiltonian_Path.py) - [Articulation Point](graphs/Articulation_Point.py) +- [Strongly Connected Components - Kosaraju's Algorithm](graphs/SCC_Kosaraju.py) - [Strongly Connected Components - Tarjan's Algorithm](graphs/SCC_Tarjan.py) - [Bipartite Graph](graphs/Bipartite_Graph.py) From 067b15ac9cff3b8fb4d7a5f40b86ae4794ec93ad Mon Sep 17 00:00:00 2001 From: Akash Kumar Bhagat Date: Thu, 17 Dec 2020 23:59:46 +0530 Subject: [PATCH 3/4] Sample IO added --- Python/graphs/SCC_Kosaraju.py | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Python/graphs/SCC_Kosaraju.py b/Python/graphs/SCC_Kosaraju.py index 1bbfc99cdf..c9ce32c2e8 100644 --- a/Python/graphs/SCC_Kosaraju.py +++ b/Python/graphs/SCC_Kosaraju.py @@ -104,3 +104,51 @@ def SCC_Kosaraju(n,graph): print("The Strongly Connected Componentes in the given Directed Graph are :") SCC_Kosaraju(n, graph) +""" + +Sample Input / Output + + 1--------->5 4 + ^ / \ ^ + \ / \ / + \ / \ / + \ / \ / + \V 3 + 2 + +Enter the number of vertex and edges: 5 5 +Enter the edges: +1 5 +5 2 +2 1 +5 3 +3 4 +The Strongly Connected Componentes in the given Directed Graph are : +[ 5 2 1 ] +[ 3 ] +[ 4 ] + + + 1-------->4----------->5 + ^ | /^ + | | / \ + | | / \ + | | V \ + | V 6------>7 + 2<--------3 + +Enter the number of vertex and edges: 7 8 +Enter the edges: +1 4 +2 1 +3 2 +4 3 +4 5 +5 6 +6 7 +7 5 +The Strongly Connected Componentes in the given Directed Graph are : +[ 4 3 2 1 ] +[ 6 7 5 ] + +""" From 23b65581ef363cc5421427c56eaa743dbf6dd77a Mon Sep 17 00:00:00 2001 From: Akash Kumar Bhagat Date: Fri, 18 Dec 2020 00:02:37 +0530 Subject: [PATCH 4/4] PEP8 formated --- Python/graphs/SCC_Kosaraju.py | 55 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/Python/graphs/SCC_Kosaraju.py b/Python/graphs/SCC_Kosaraju.py index c9ce32c2e8..6f45690a0e 100644 --- a/Python/graphs/SCC_Kosaraju.py +++ b/Python/graphs/SCC_Kosaraju.py @@ -28,65 +28,70 @@ """ from collections import defaultdict -def DFS(graph,node,visited,stack,display): - + +def DFS(graph, node, visited, stack, display): + # Mark the node Visited - visited[node]=True + visited[node] = True for i in graph[node]: - # Recursively call all DFS() function to all its unvisited adjacent nodes + # Recursively call all DFS() function to all its unvisited adjacent + # nodes if not visited[i]: - DFS(graph,i,visited,stack,display) + DFS(graph, i, visited, stack, display) # If the display is True, then Display the SCC if display: - print(node,end=" ") + print(node, end=" ") else: stack.append(node) -# Reverse_Graph() function reverse all the directed edges of the graph +# Reverse_Graph() function reverse all the directed edges of the graph + + def Reverse_Graph(graph): - rev_graph=defaultdict(list) + rev_graph = defaultdict(list) for i in graph.keys(): for j in graph[i]: rev_graph[j].append(i) - + # Return the reversed graph return rev_graph -def SCC_Kosaraju(n,graph): - + +def SCC_Kosaraju(n, graph): + # Initilize the Stack - stack=[] + stack = [] # To keep a track of all the visited nodes - visited=[False]*(n+1) + visited = [False] * (n + 1) - for i in range(1,n+1): + for i in range(1, n + 1): # (1) Recursively call DFS() to push the unvisited nodes into the stack if not visited[i]: - DFS(graph,i,visited,stack,False) - + DFS(graph, i, visited, stack, False) + # (2) Reverse the Graph - rev_graph=Reverse_Graph(graph) - + rev_graph = Reverse_Graph(graph) + # Mark all the nodes Unvisited - visited=[False]*(n+1) + visited = [False] * (n + 1) while stack: - node=stack.pop() + node = stack.pop() - # For each unvisited node in the stack, call DFS() + # (3) For each unvisited node in the stack, call DFS() if not visited[node]: # Print the SCC in formated way - print("[ ",end="") - DFS(rev_graph,node,visited,stack,True) + print("[ ", end="") + DFS(rev_graph, node, visited, stack, True) print("]") - + if __name__ == "__main__": @@ -101,7 +106,7 @@ def SCC_Kosaraju(n,graph): # Directed Graph graph[a] += [b] - print("The Strongly Connected Componentes in the given Directed Graph are :") + print("The Strongly Connected Componentes in the given Directed Graph :") SCC_Kosaraju(n, graph) """