Articulation Points in Graph in DSA C++ - Time & Space Complexity
We want to understand how the time needed to find articulation points changes as the graph grows.
How does the algorithm's work increase when the number of nodes and edges increases?
Analyze the time complexity of the following code snippet.
void dfs(int u, int parent) {
visited[u] = true;
disc[u] = low[u] = ++time;
int children = 0;
for (int v : graph[u]) {
if (!visited[v]) {
children++;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (parent != -1 && low[v] >= disc[u])
articulation[u] = true;
} else if (v != parent) {
low[u] = min(low[u], disc[v]);
}
}
if (parent == -1 && children > 1)
articulation[u] = true;
}
This code finds articulation points using a depth-first search on the graph.
- Primary operation: The depth-first search (DFS) visits each node and explores all its edges.
- How many times: Each node is visited once, and each edge is checked once during DFS.
As the number of nodes and edges grows, the DFS explores more connections, increasing work roughly in proportion.
| Input Size (n nodes, m edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 25 operations |
| 100 nodes, 200 edges | About 300 operations |
| 1000 nodes, 5000 edges | About 6000 operations |
Pattern observation: The work grows roughly linearly with the sum of nodes and edges.
Time Complexity: O(n + m)
This means the time grows linearly with the number of nodes plus edges in the graph.
[X] Wrong: "The algorithm checks every possible path, so it must be exponential time."
[OK] Correct: The DFS visits each node and edge only once, avoiding repeated work, so it runs in linear time, not exponential.
Understanding this linear time complexity helps you explain how graph algorithms efficiently find critical points, a valuable skill in many coding challenges.
"What if the graph is represented using an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of articulation points
An articulation point is a vertex that, if removed, breaks the graph into more pieces (connected components).Step 2: Compare options with definition
Only A vertex which, when removed, increases the number of connected components describes this property correctly; others describe different vertex properties.Final Answer:
A vertex which, when removed, increases the number of connected components -> Option BQuick Check:
Articulation point = vertex increasing components when removed [OK]
- Confusing articulation point with highest degree vertex
- Thinking articulation point forms cycles
- Assuming articulation point connects to all vertices
Solution
Step 1: Recall correct syntax for 2D vector declaration
In C++, a vector of vectors is declared as vector name; to represent adjacency lists.Step 2: Check each option
vector adj; matches correct syntax; A, B and D have syntax errors.Final Answer:
vector adj; -> Option AQuick Check:
2D vector syntax = vector [OK]
- Using array syntax instead of vector
- Incorrect template syntax
- Missing angle brackets for nested vectors
int timer = 0;
vector<int> disc(4, -1), low(4, -1);
vector<bool> visited(4, false), isAP(4, false);
vector adj = {{1, 2}, {0, 2}, {0, 1, 3}, {2}};
void dfs(int u, int parent) {
visited[u] = true;
disc[u] = low[u] = timer++;
int children = 0;
for (int v : adj[u]) {
if (v == parent) continue;
if (!visited[v]) {
children++;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (parent != -1 && low[v] >= disc[u])
isAP[u] = true;
} else {
low[u] = min(low[u], disc[v]);
}
}
if (parent == -1 && children > 1)
isAP[u] = true;
}
dfs(0, -1);
vector<int> result;
for (int i = 0; i < 4; i++) {
if (isAP[i]) result.push_back(i);
}
for (int x : result) cout << x << " ";What will be the output?
Solution
Step 1: Analyze the graph structure and DFS traversal
The graph edges are: 0-1, 0-2, 1-2, 2-3 (triangle 0-1-2 + pendant 3 on 2). DFS from 0 visits 1 then 2 then 3; when back to 0, 2 already visited so root children=1 (not AP).Step 2: Check articulation point conditions in code
Root children=1 (<=1, not AP). For non-root u=2 (parent=1), low[3]=3 >= disc[2]=2 so isAP[2]=true. No others. Output is 2.Final Answer:
2 -> Option AQuick Check:
Root children=1 and vertex 2 disconnects 3 = 2 [OK]
- Missing root articulation point condition
- Confusing low and disc arrays
- Ignoring parent check in DFS
void dfs(int u, int parent) {
visited[u] = true;
disc[u] = low[u] = timer++;
int children = 0;
for (int v : adj[u]) {
if (!visited[v]) {
children++;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= disc[u])
isAP[u] = true;
} else if (v != parent) {
low[u] = min(low[u], disc[v]);
}
}
if (parent == -1 && children > 1)
isAP[u] = true;
}What is the bug in this code?
Solution
Step 1: Understand articulation point condition for non-root nodes
For non-root nodes, isAP[u] should be set only if parent != -1 and low[v] >= disc[u]. The code misses the parent != -1 check before setting isAP[u].Step 2: Verify other parts of code
Timer is incremented correctly, visited[u] is set true, low[u] updated properly. So only missing parent check is the bug.Final Answer:
Missing check for parent != -1 before marking isAP[u] -> Option DQuick Check:
Parent check needed before marking articulation point [OK]
- Marking root as articulation point incorrectly
- Confusing order of visited and timer increment
- Ignoring parent in back edge condition
Solution
Step 1: Analyze graph connectivity and removal effects
Vertices 0,1,2 form a triangle (cycle), so none of them alone disconnects graph except vertex 1 which connects to 3 and 4. Removing 1 disconnects 3 and 4. Removing 3 disconnects 4. So 1 and 3 are articulation points.Step 2: Confirm articulation points
Vertex 1 connects two parts: cycle and chain (3-4). Vertex 3 connects 4 only. Removing 1 or 3 increases components. Vertex 0, 2, 4 are not articulation points.Final Answer:
1 3 -> Option CQuick Check:
Removing 1 or 3 disconnects graph = 1 3 [OK]
- Including vertices in cycles as articulation points
- Missing leaf node articulation points
- Confusing articulation points with bridges
Ready to prove it?
Pass the test and this pattern moves unknown
