1192-critical-connections-in-a-network¶
Try it on leetcode
Description¶
There are n
servers numbered from 0
to n - 1
connected by undirected server-to-server connections
forming a network where connections[i] = [ai, bi]
represents a connection between servers ai
and bi
. Any server can reach other servers directly or indirectly through the network.
A critical connection is a connection that, if removed, will make some servers unable to reach some other server.
Return all critical connections in the network in any order.
Example 1:

Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]] Output: [[1,3]] Explanation: [[3,1]] is also accepted.
Example 2:
Input: n = 2, connections = [[0,1]] Output: [[0,1]]
Constraints:
2 <= n <= 105
n - 1 <= connections.length <= 105
0 <= ai, bi <= n - 1
ai != bi
- There are no repeated connections.
Solution(Python)¶
class Solution:
def criticalConnections(
self, n: int, connections: List[List[int]]
) -> List[List[int]]:
return self.optmial(n, connections)
# Time Complexity: O(E*(V+E))
# Space Complexity: O(V+E)
def bruteforce(self, n: int, connections: List[List[int]]) -> List[List[int]]:
# create graph adj list
adjList = defaultdict(set)
for x, y in connections:
adjList[x].add(y)
adjList[y].add(x)
res = []
# initial number of connected components
total_com = 0
visited = [False] * n
for i in range(n):
for j in range(n):
if visited[i] == False and i != j:
total_com += 1
self.dfs(adjList, i, visited)
# remove each E and see if graph remains connected
for x, y in connections:
visited = [False] * n
adjList[x].remove(y)
adjList[y].remove(x)
cur_comp = 0
for i in range(n):
if visited[i] == False:
cur_comp += 1
self.dfs(adjList, i, visited)
# if removal of E increases number of connected compponents then it's a bridge
if cur_comp > total_com:
res.append([x, y])
adjList[x].add(y)
adjList[y].add(x)
return res
# Time Complexity: O((V+E))
# Space Complexity: O(V+E)
def dfs(self, adjList, i, visited):
if visited[i]:
return
visited[i] = True
for j in adjList[i]:
if not visited[j]:
self.dfs(adjList, j, visited)
# Time Complexity: O(V+E)
# Space Complexity: O(V+E)
def optmial(self, n: int, connections: List[List[int]]) -> List[List[int]]:
self.low = [0] * n
self.disc = [0] * n
self.res = []
self.time = 1
self.adjList = defaultdict(set)
for x, y in connections:
self.adjList[x].add(y)
self.adjList[y].add(x)
for u in range(n):
if not self.disc[u]:
self.optimal_df_util(u, u)
return self.res
def optimal_df_util(self, u, p):
self.time += 1
self.low[u] = self.disc[u] = self.time
for v in self.adjList[u]:
if v == p:
continue
if not self.disc[v]:
self.optimal_df_util(v, u)
if self.disc[u] < self.low[v]:
self.res.append([u, v])
self.low[u] = min(self.low[u], self.low[v])
else:
self.low[u] = min(self.low[u], self.disc[v])