A Strongly Connected Component of a directed graph is a maximal group of vertices where each vertex is reachable from any other vertex in the same group.
from collections import defaultdict
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = defaultdict(list)
def add_edge(self, u, v):
self.graph[u].append(v)
def dfs(self, v, visited, stack=None):
visited[v] = True
if stack is not None:
stack.append(v)
for neighbor in self.graph[v]:
if not visited[neighbor]:
self.dfs(neighbor, visited, stack)
def fill_order(self, v, visited, stack):
visited[v] = True
for neighbor in self.graph[v]:
if not visited[neighbor]:
self.fill_order(neighbor, visited, stack)
stack.append(v)
def transpose(self):
g = Graph(self.V)
for v in self.graph:
for neighbor in self.graph[v]:
g.add_edge(neighbor, v)
return g
def print_scc(self):
stack = []
visited = [False] * self.V
for i in range(self.V):
if not visited[i]:
self.fill_order(i, visited, stack)
transpose_graph = self.transpose()
visited = [False] * self.V
print("Strongly Connected Components:")
while stack:
v = stack.pop()
if not visited[v]:
scc_stack = []
transpose_graph.dfs(v, visited, scc_stack)
print(scc_stack)
# Usage
g = Graph(8)
edges = [(0,1),(1,2),(2,3),(2,4),(3,0),(4,5),(5,6),(6,4),(6,7)]
for u, v in edges:
g.add_edge(u, v)
g.print_scc()
A bridge (or cut-edge) in an undirected graph is an edge which, when removed, increases the number of connected components.
def dfs_bridges(u, visited, parent, disc, low, time, graph, bridges):
visited[u] = True
disc[u] = low[u] = time[0]
time[0] += 1
for v in graph[u]:
if not visited[v]:
parent[v] = u
dfs_bridges(v, visited, parent, disc, low, time, graph, bridges)
low[u] = min(low[u], low[v])
if low[v] > disc[u]:
bridges.append((u, v))
elif v != parent[u]:
low[u] = min(low[u], disc[v])
def find_bridges(V, edges):
graph = [[] for _ in range(V)]
for u,v in edges:
graph[u].append(v)
graph[v].append(u) # undirected
visited = [False] * V
disc = [float('inf')] * V
low = [float('inf')] * V
parent = [-1] * V
time = [0]
bridges = []
for i in range(V):
if not visited[i]:
dfs_bridges(i, visited, parent, disc, low, time, graph, bridges)
return bridges
# Usage
V = 5
edges = [(1, 0), (0, 2), (2, 1), (0, 3), (3, 4)]
print("Bridges in graph:", find_bridges(V, edges))