hard Critical Connections in a Network
Problem Statement
You are given n servers numbered from 0 to n-1, connected by some number of undirected connections 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 servers.
Return all critical connections in the network.
Examples
Example 1:
- Input: n = 5, connections =
[[0, 1], [1, 2], [2, 3], [3, 4], [2, 4]] - Expected Output:
[[1,2],[0,1]]
- Justification: Removing either
[0, 1]or[1, 2]will split the network into separate parts, making some servers unreachable from others.
Example 2:
- Input: n = 4, connections =
[[0, 1], [0, 2], [1, 2], [2, 3]] - Expected Output:
[[2, 3]]
- Justification: Removing
[2, 3]will isolate server3, making it unreachable from the other servers.
Example 3:
- Input: n = 6, connections =
[[0, 1], [1, 2], [2, 0], [1, 3], [3, 4], [4, 5], [5, 3]] - Expected Output:
[[1, 3]]
- Justification: Removing
[1, 3]will disconnect servers3,4, and5from the rest of the network.
Constraints:
- 2 <= n <= 105
- n - 1 <= connections.length <= 105
- 0 <= ai, bi <= n - 1
- ai != bi
- There are no repeated connections.
Try it yourself
Try solving this question here:
✅ Solution Critical Connections in a Network
Problem Statement
You are given n servers numbered from 0 to n-1, connected by some number of undirected connections 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 servers.
Return all critical connections in the network.
Examples
Example 1:
- Input: n = 5, connections =
[[0, 1], [1, 2], [2, 3], [3, 4], [2, 4]] - Expected Output:
[[1,2],[0,1]]
- Justification: Removing either
[0, 1]or[1, 2]will split the network into separate parts, making some servers unreachable from others.
Example 2:
- Input: n = 4, connections =
[[0, 1], [0, 2], [1, 2], [2, 3]] - Expected Output:
[[2, 3]]
- Justification: Removing
[2, 3]will isolate server3, making it unreachable from the other servers.
Example 3:
- Input: n = 6, connections =
[[0, 1], [1, 2], [2, 0], [1, 3], [3, 4], [4, 5], [5, 3]] - Expected Output:
[[1, 3]]
- Justification: Removing
[1, 3]will disconnect servers3,4, and5from the rest of the network.
Constraints:
- 2 <= n <= 105
- n - 1 <= connections.length <= 105
- 0 <= ai, bi <= n - 1
- ai != bi
- There are no repeated connections.
Solution
To solve this problem, we can use Depth First Search (DFS). The key idea is to identify bridges in the graph. A bridge is an edge that, when removed, splits the graph into disconnected parts. By using DFS, we can record the discovery and low-link values of each node. The discovery time is the time at which a node is first visited, and the low-link value is the smallest discovery time reachable from the node. If a node cannot reach an ancestor node through its descendants, then the edge leading to that descendant is a critical connection.
This approach is effective because it systematically explores all nodes and edges using DFS, ensuring that all potential critical connections are examined. The use of discovery and low-link values helps in efficiently identifying critical connections with a time complexity of
Step-by-Step Algorithm
-
Initialize Data Structures:
- Create an adjacency list
graphto represent the network of servers. - Create arrays
discandlowto store the discovery times and the lowest discovery times reachable for each node, initialized to-1. - Initialize a list
resto store the critical connections. - Set a global
timevariable to track the discovery time during DFS.
- Create an adjacency list
-
Build the Graph:
- For each connection
[u, v]inconnections, addvto the adjacency list ofuanduto the adjacency list ofv.
- For each connection
-
DFS Function:
- Define a recursive DFS function that takes the current node
u, its parent nodeparent, thedisc,low,graph, andresas arguments. - Set
disc[u]andlow[u]to the currenttime, then incrementtime. - For each neighbor
vofuin the graph:- If
vis the parent ofu, skip it. - If
vhas not been visited (disc[v] == -1):- Recursively call DFS on
vwithuas the parent. - Update
low[u]to the minimum oflow[u]andlow[v]. - If
low[v] > disc[u], add[u, v]toresas it is a critical connection.
- Recursively call DFS on
- If
vhas already been visited and is not the parent, updatelow[u]to the minimum oflow[u]anddisc[v].
- If
- Define a recursive DFS function that takes the current node
-
Run DFS:
- Call the DFS function starting from node
0with-1as the parent.
- Call the DFS function starting from node
-
Return Result:
- Return the list
rescontaining all the critical connections.
- Return the list
Algorithm Walkthrough
Let's walk through the algorithm with n = 5 and connections = [[0, 1], [1, 2], [2, 3], [3, 4], [2, 4]].
-
Initialize Data Structures:
graph = [[], [], [], [], []]disc = [-1, -1, -1, -1, -1]low = [-1, -1, -1, -1, -1]res = []time = 0
-
Build the Graph:
- After processing
connections:graph = [[1], [0, 2], [1, 3, 4], [2, 4], [3, 2]]
- After processing
-
Run DFS starting from node 0:
-
DFS on node 0:
disc[0] = 0,low[0] = 0,time = 1- Visit neighbor
1.
-
DFS on node 1:
disc[1] = 1,low[1] = 1,time = 2- Skip neighbor
0(parent). - Visit neighbor
2.
-
DFS on node 2:
disc[2] = 2,low[2] = 2,time = 3- Skip neighbor
1(parent). - Visit neighbor
3.
-
DFS on node 3:
disc[3] = 3,low[3] = 3,time = 4- Skip neighbor
2(parent). - Visit neighbor
4.
-
DFS on node 4:
-
disc[4] = 4,low[4] = 4,time = 5 -
Skip neighbor
3(parent). -
Visit neighbor
2. -
Node 2 has been visited already, and it's not the parent of node 4. Update
low[4] = min(low[4], disc[2]) = min(4, 2) = 2.
-
-
Backtrack to node 3:
low[3] = min(low[3], low[4]) = min(3, 2) = 2.low[4] > disc[3]is not true (2 > 3is false). So[3, 4]is not a critical connection.
-
Backtrack to node 2:
low[2] = min(low[2], low[3]) = min(2, 2) = 2.-
Visit neighbor
4again. -
Node 4 has been visited already, and it's not the parent of node 2. Update
low[2] = min(low[2], disc[4]) = min(2, 4) = 2. -
Backtrack to node 1:
low[1] = min(low[1], low[2]) = min(1, 2) = 1. -
low[2] > disc[1]is true (2 > 1is true). So[1, 2]is a critical connection. Add[1, 2]tores.
-
-
Backtrack to node 0:
low[0] = min(low[0], low[1]) = min(0, 1) = 0.low[1] > disc[0]is true (1 > 0is true). So[0, 1]is a critical connection. Add[0, 1]tores.
-
-
Result:
res = [[1, 2], [0, 1]].
The final result is [[1, 2], [0, 1]], meaning removing either of these connections will split the network into separate parts.
Code
import java.util.*;
public class Solution {
private int time = 0; // Time counter used in DFS
public List<List<Integer>> criticalConnections(
int n,
List<List<Integer>> connections
) {
// Initialize graph, discovery time and low time arrays
List<Integer>[] graph = new ArrayList[n];
int[] disc = new int[n],
low = new int[n];
Arrays.fill(disc, -1); // Mark all nodes as unvisited
List<List<Integer>> res = new ArrayList<>();
// Build the graph
for (int i = 0; i < n; i++) {
graph[i] = new ArrayList<>();
}
for (List<Integer> conn : connections) {
graph[conn.get(0)].add(conn.get(1));
graph[conn.get(1)].add(conn.get(0));
}
// Perform DFS from the first node
dfs(0, -1, disc, low, graph, res);
return res;
}
private void dfs(
int u,
int parent,
int[] disc,
int[] low,
List<Integer>[] graph,
List<List<Integer>> res
) {
disc[u] = low[u] = ++time; // Initialize discovery and low times
for (int v : graph[u]) {
if (v == parent) continue; // Skip the parent node
if (disc[v] == -1) {
// If v is not visited
dfs(v, u, disc, low, graph, res);
low[u] = Math.min(low[u], low[v]);
if (low[v] > disc[u]) {
// Check for a critical connection
res.add(Arrays.asList(u, v));
}
} else {
low[u] = Math.min(low[u], disc[v]); // Update low time of u
}
}
}
public static void main(String[] args) {
Solution sol = new Solution();
// Example 1
int n1 = 5;
List<List<Integer>> connections1 = Arrays.asList(
Arrays.asList(0, 1),
Arrays.asList(1, 2),
Arrays.asList(2, 3),
Arrays.asList(3, 4),
Arrays.asList(2, 4)
);
System.out.println(sol.criticalConnections(n1, connections1)); // [[2, 3], [3, 4]]
// Example 2
int n2 = 4;
List<List<Integer>> connections2 = Arrays.asList(
Arrays.asList(0, 1),
Arrays.asList(0, 2),
Arrays.asList(1, 2),
Arrays.asList(2, 3)
);
System.out.println(sol.criticalConnections(n2, connections2)); // [[2, 3]]
// Example 3
int n3 = 6;
List<List<Integer>> connections3 = Arrays.asList(
Arrays.asList(0, 1),
Arrays.asList(1, 2),
Arrays.asList(2, 0),
Arrays.asList(1, 3),
Arrays.asList(3, 4),
Arrays.asList(4, 5),
Arrays.asList(5, 3)
);
System.out.println(sol.criticalConnections(n3, connections3)); // [[1, 3]]
}
}
Complexity Analysis
Time Complexity: The algorithm runs in
Space Complexity: The space complexity is
🤖 Don't fully get this? Learn it with Claude
Stuck on Critical Connections in a Network? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Critical Connections in a Network** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Critical Connections in a Network** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Critical Connections in a Network**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Critical Connections in a Network**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.