Bipartite Graph Check in DSA C++ - Time & Space Complexity
We want to know how long it takes to check if a graph can be split into two groups without edges inside the same group.
How does the time needed grow as the graph gets bigger?
Analyze the time complexity of the following code snippet.
bool isBipartite(int V, vector<int> adj[]) {
vector<int> color(V, -1);
for (int i = 0; i < V; i++) {
if (color[i] == -1) {
queue<int> q;
q.push(i);
color[i] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (auto v : adj[u]) {
if (color[v] == -1) {
color[v] = 1 - color[u];
q.push(v);
} else if (color[v] == color[u]) {
return false;
}
}
}
}
}
return true;
}
This code checks if a graph is bipartite by coloring nodes using breadth-first search.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each vertex and its edges once during BFS.
- How many times: Each vertex is visited once, and each edge is checked once (in an undirected graph, edges appear twice in adjacency lists).
As the number of vertices and edges grow, the time grows roughly in proportion to their sum.
| Input Size (V, E) | Approx. Operations |
|---|---|
| 10 vertices, 15 edges | About 25 checks (10 vertices + 15 edges) |
| 100 vertices, 200 edges | About 300 checks (100 + 200) |
| 1000 vertices, 5000 edges | About 6000 checks (1000 + 5000) |
Pattern observation: The work grows linearly with the number of vertices plus edges.
Time Complexity: O(V + E)
This means the time to check grows in a straight line with the total number of vertices and edges.
[X] Wrong: "The check takes time proportional to the square of vertices because of nested loops."
[OK] Correct: The code visits each edge and vertex only once, not repeatedly for every vertex, so it grows linearly, not quadratically.
Understanding this time complexity helps you explain how graph traversal algorithms scale, a key skill in many coding challenges and real-world problems.
"What if the graph was represented using an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
bipartite?Solution
Step 1: Understand bipartite graph definition
A bipartite graph means vertices can be split into two sets where no edge connects vertices within the same set.Step 2: Compare options with definition
Its vertices can be divided into two groups with no edges inside the same group matches this definition exactly, while others describe unrelated properties.Final Answer:
Its vertices can be divided into two groups with no edges inside the same group -> Option CQuick Check:
Bipartite = Two groups, no internal edges [OK]
- Confusing bipartite with equal vertices and edges
- Thinking bipartite graphs must have cycles
- Assuming all vertices have same degree
Solution
Step 1: Identify adjacency list structure
An adjacency list for a graph with n vertices is best represented as vector of vectors: vector graph(n);Step 2: Check other options
vector<int> graph(n); is a vector of ints, not suitable for adjacency lists. int graph[n][n]; is a 2D array but less flexible. map graph; is a map of int to int, not adjacency list.Final Answer:
vector graph(n); -> Option AQuick Check:
Adjacency list = vector of vectors [OK]
- Using vector<int> instead of vector
- Using fixed size arrays limiting flexibility
- Using map which is not adjacency list
int n = 4;
vector graph = {{1,3}, {0,2}, {1,3}, {0,2}};
vector<int> color(n, -1);
function dfs = [&](int node, int c) {
color[node] = c;
for (int neigh : graph[node]) {
if (color[neigh] == -1) {
if (!dfs(neigh, 1 - c)) return false;
} else if (color[neigh] == c) {
return false;
}
}
return true;
};
bool result = true;
for (int i = 0; i < n; i++) {
if (color[i] == -1) {
if (!dfs(i, 0)) {
result = false;
break;
}
}
}
cout << (result ? "YES" : "NO") << endl;Solution
Step 1: Analyze graph structure
The graph edges connect vertices 0-1, 0-3, 1-2, 2-3 forming a square (even cycle), which is bipartite.Step 2: Trace DFS coloring
DFS colors nodes alternatingly. No adjacent nodes share the same color, so dfs returns true for all nodes.Final Answer:
YES -> Option DQuick Check:
Even cycle graph is bipartite = YES [OK]
- Assuming all cycles are non-bipartite
- Confusing color assignment logic
- Ignoring disconnected components
bool dfs(int node, int c, vector& graph, vector<int>& color) {
color[node] = c;
for (int neigh : graph[node]) {
if (color[neigh] == -1) {
dfs(neigh, 1 - c, graph, color);
} else if (color[neigh] == c) {
return false;
}
}
return true;
}Solution
Step 1: Check recursive call handling
The recursive dfs call result is not checked. If it returns false, the function should also return false immediately.Step 2: Explain fix
Adding 'if (!dfs(...)) return false;' ensures early exit on conflict detection.Final Answer:
Missing return value check for recursive dfs call -> Option AQuick Check:
Always check recursive call results in DFS [OK]
- Ignoring recursive call return values
- Assigning wrong colors
- Using wrong data structures for graph
Solution
Step 1: Identify cycles in the graph
The edges form a cycle: 1-2-3-4-1 which has 4 edges (even length). However, the full cycle including vertices 0-1-4-3-2-1 forms a cycle of length 5 (odd cycle): 0-1-4-3-2-1 (0-1,1-4,4-3,3-2,2-1).Step 2: Check bipartite condition
Since the graph contains an odd cycle of length 5, it is not bipartite.Step 3: Re-examine options
The graph is bipartite because it has no odd cycles is false. The graph is not bipartite because it contains an odd cycle is true. The graph is bipartite because all vertices have degree 2 is incorrect reasoning. The graph is not bipartite because it is disconnected is false because the graph is connected.Final Answer:
The graph is not bipartite because it contains an odd cycle -> Option BQuick Check:
Odd cycle means not bipartite [OK]
- Miscounting cycle length
- Confusing connectivity with bipartite property
- Assuming degree affects bipartite
Ready to prove it?
Pass the test and this pattern moves unknown
