Possible Bipartition
Problem
Given n people (1..n) and a list of pairs that dislike each other, decide whether everyone can be split into two groups with no dislike edge inside a group.
n=4, dislikes=[[1,2],[1,3],[2,4]]truefrom collections import defaultdict, deque
def possibleBipartition(n, dislikes):
g = defaultdict(list)
for a, b in dislikes:
g[a].append(b); g[b].append(a)
color = {}
for s in range(1, n + 1):
if s in color: continue
color[s] = 0
q = deque([s])
while q:
u = q.popleft()
for v in g[u]:
if v not in color:
color[v] = 1 - color[u]
q.append(v)
elif color[v] == color[u]:
return False
return True
function possibleBipartition(n, dislikes) {
const g = Array.from({ length: n + 1 }, () => []);
for (const [a, b] of dislikes) { g[a].push(b); g[b].push(a); }
const color = new Array(n + 1).fill(-1);
for (let s = 1; s <= n; s++) {
if (color[s] !== -1) continue;
color[s] = 0;
const q = [s]; let head = 0;
while (head < q.length) {
const u = q[head++];
for (const v of g[u]) {
if (color[v] === -1) { color[v] = 1 - color[u]; q.push(v); }
else if (color[v] === color[u]) return false;
}
}
}
return true;
}
class Solution {
public boolean possibleBipartition(int n, int[][] dislikes) {
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i <= n; i++) g.add(new ArrayList<>());
for (int[] e : dislikes) { g.get(e[0]).add(e[1]); g.get(e[1]).add(e[0]); }
int[] color = new int[n + 1];
Arrays.fill(color, -1);
for (int s = 1; s <= n; s++) {
if (color[s] != -1) continue;
color[s] = 0;
Deque<Integer> q = new ArrayDeque<>(); q.offer(s);
while (!q.isEmpty()) {
int u = q.poll();
for (int v : g.get(u)) {
if (color[v] == -1) { color[v] = 1 - color[u]; q.offer(v); }
else if (color[v] == color[u]) return false;
}
}
}
return true;
}
}
bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
vector<vector<int>> g(n + 1);
for (auto& e : dislikes) { g[e[0]].push_back(e[1]); g[e[1]].push_back(e[0]); }
vector<int> color(n + 1, -1);
for (int s = 1; s <= n; s++) {
if (color[s] != -1) continue;
color[s] = 0;
queue<int> q; q.push(s);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : g[u]) {
if (color[v] == -1) { color[v] = 1 - color[u]; q.push(v); }
else if (color[v] == color[u]) return false;
}
}
}
return true;
}
Explanation
Splitting people into two groups with no dislike inside a group is exactly a 2-coloring problem. If we treat each dislike as an edge, the question becomes: can we color the graph with two colors so that no edge joins two same-colored nodes? That property is called being bipartite.
We build an adjacency list from the dislikes, then run a BFS from every uncolored person (the graph may have several disconnected pieces). The starting person gets color 0.
When we visit a person u and look at a disliked neighbor v: if v has no color yet, we give it the opposite color with color[v] = 1 - color[u]. If v already has the same color as u, two people who dislike each other are forced into the same group — a contradiction — so we return false.
If we finish coloring everyone without any clash, a valid split exists and we return true.
Example: n=4, dislikes [[1,2],[1,3],[2,4]]. Color 1 = A, then 2 and 3 = B, then 4 = A. No edge connects same colors, so groups {1,4} and {2,3} work and the answer is true.