Is Graph Bipartite?
Problem
Section titled “Problem”There is an undirected graph with n nodes, where each node is numbered between 0 and n - 1. You are given a 2D array graph, where graph[u] is an array of nodes that node u is adjacent to. More formally, for each v in graph[u], there is an undirected edge between node u and node v. The graph has the following properties:
- There are no self-edges (
graph[u]does not containu). - There are no parallel edges (
graph[u]does not contain duplicate values). - If
vis ingraph[u], thenuis ingraph[v](the graph is undirected). - The graph may not be connected, meaning there may be two nodes
uandvsuch that there is no path between them.
A graph is bipartite if the nodes can be partitioned into two independent sets A and B such that every edge in the graph connects a node in set A and a node in set B.
Return true if and only if it is bipartite.
Solution approach
Section titled “Solution approach”Intuition
Section titled “Intuition”A graph is bipartite if we can paint every vertex with one of two colours so that no edge joins two vertices of the same colour. A DFS can try this greedily: paint the start vertex colour 1, then every unvisited neighbour gets the opposite colour. If we ever reach an already painted neighbour with the same colour as the current vertex, the two-colouring is impossible.
The graph may be disconnected, so the DFS is started from every vertex that has not been painted yet.
Algorithm
Section titled “Algorithm”isBipartitecallsdfs(graph, n), which createsvisited(0 means unpainted) and startsdfs_helperfrom each unpainted vertexiwith colour1.dfs_helperpaintsnodewithcolor, then looks at each neighbournbr:- if
nbris not the parentparand is unpainted, recurse with colour3 - color(switching between1and2); propagate afalseresult; - otherwise, if
visited[nbr] == color, the edge joins two same-coloured vertices, so returnfalse.
- if
- If every component is painted without conflict, return
true.
Complexity
Section titled “Complexity”- Time: — the DFS itself visits each vertex and edge once, but
dfs_helpertakesGraphby value, so each of the calls copies the whole adjacency list. - Space: — the recursion stack can be frames deep, and each frame holds its own copy of
Graph.
Edge cases
Section titled “Edge cases”- Disconnected graph: the loop in
dfsstarts a new DFS for every component. - Odd cycle such as a triangle: the last vertex meets a neighbour painted with its own colour, so the answer is
false.
class Solution { public: bool dfs_helper(vector<vector<int>> Graph, vector<int>& visited, int par, int node, int color) { visited[node] = color; // painted for (auto nbr : Graph[node]) { // traversing nbrs if (nbr != par and visited[nbr] == 0) { bool value = dfs_helper(Graph, visited, node, nbr, 3 - color); if (value == false) return false; } else if (visited[nbr] == color) return false; } return true; }
bool dfs(vector<vector<int>> Graph, int N) { vector<int> visited(N + 1); int color = 1; for (int i = 0; i < N; i++) { if (visited[i] == 0) { bool ans = dfs_helper(Graph, visited, -1, i, 1); if (ans == false) return ans; } } return true; }
bool isBipartite(vector<vector<int>>& graph) { int n = graph.size(); return dfs(graph, n); }};Give it a try first
Attempt the problem on LeetCode — the code will still be here.