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:
2
/ |
1 |
critical | \ |
| 0
3
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
class Solution:
rank = {}
graph = defaultdict(list)
conn_dict = {}
def criticalConnections(
self,
n: int,
connections: List[List[int]]
) -> List[List[int]]:
self.formGraph(n, connections)
self.dfs(0, 0)
return [[u, v] for u, v in self.conn_dict]
def dfs(self, node: int, discovery_rank: int) -> int:
# node is already visited
if self.rank[node]:
return self.rank[node]
# Update rank
self.rank[node] = discovery_rank
# This is the max we have seen till now.
# So we start with this instead of INT_MAX or something.
min_rank = discovery_rank + 1
for neighbor in self.graph[node]:
# Skip the parent.
if self.rank[neighbor] and self.rank[neighbor] == discovery_rank - 1:
continue
recursive_rank = self.dfs(neighbor, discovery_rank + 1)
# Step 1, check if this edge needs to be discarded.
if recursive_rank <= discovery_rank:
del self.conn_dict[(min(node, neighbor), max(node, neighbor))]
# Step 2, update the minRank if needed.
min_rank = min(min_rank, recursive_rank)
return min_rank
def formGraph(self, n: int, connections: List[List[int]]):
# Reinitialize for each test case
self.rank = {}
self.graph = defaultdict(list)
self.conn_dict = {}
# Default rank for unvisited nodes is "null"
for i in range(n):
self.rank[i] = None
for edge in connections:
# Bidirectional edges.
u, v = edge[0], edge[1]
self.graph[u].append(v)
self.graph[v].append(u)
self.conn_dict[(min(u, v), max(u, v))] = 1
|