0886 Possible Bipartition#
Problem#
We want to split a group of n people (labeled from 1
to n
) into two groups of any size. Each person may dislike some other people, and they should not go into the same group.
Given the integer n
and the array dislikes where dislikes[i] = [ai, bi]
indicates that the person labeled ai
does not like the person labeled bi
, return true
if it is possible to split everyone into two groups in this way.
Examples#
Example 1:
Input: n = 4, dislikes = [[1,2],[1,3],[2,4]]
Output: true
Explanation: The first group has [1,4], and the second group has [2,3].
Example 2:
Input: n = 3, dislikes = [[1,2],[1,3],[2,3]]
Output: false
Explanation: We need at least 3 groups to divide them. We cannot put them in two groups.
Constraints:#
1 <= n <= 2000
0 <= dislikes.length <= 104
dislikes[i].length == 2
1 <= ai < bi <= n
All the pairs of dislikes are unique.
Analysis
we can maintain two global set to track visited nodes and their colors
the graph might not be connected. We cannot use
indegree
to check the starting vertex like in a DAG for this undirected graph.thus we need a for loop to enable the traversal algorithms, i.e., BFS, DFS
BFS
the queue only stores nodes that have not been visited/colored yet
# BFS 1: use a global variable to store the result
def possibleBipartition(N, dislikes):
# construct an undirected graph
graph = {}
for i in range(1, N+1):
graph[i] = []
for u, v in dislikes:
graph[u].append(v)
graph[v].append(u)
# color the graph using BFS
colors = {}
visited = set()
# define result
bipartition = True
def bfs(graph, u):
nonlocal bipartition
# if u is not visited, visit it and color it
# else do nothing and exit
if u not in visited:
visited.add(u)
colors[u] = 0
queue = [u]
while queue:
u = queue.pop(0)
# color the neighbors of u
for v in graph[u]:
# if v is not visited, visit, color and enqueue
if v not in visited:
visited.add(v)
colors[v] = 1 - colors[u]
queue.append(v)
else:
# if v is visited, check if the colors are different
if colors[v] == colors[u]:
bipartition = False
return
# examine all nodes
for u in graph:
bfs(graph, u)
return bipartition
# test
N = 4
dislikes = [[1,2],[1,3],[2,4]]
print(possibleBipartition(N, dislikes))
N = 3
dislikes = [[1,2],[1,3],[2,3]]
print(possibleBipartition(N, dislikes))
True
False
# BFS 2: use a local variable to store the result
def possibleBipartition(N, dislikes):
# construct an undirected graph
graph = {}
for i in range(1, N+1):
graph[i] = []
for u, v in dislikes:
graph[u].append(v)
graph[v].append(u)
# color the graph using BFS
colors = {}
visited = set()
# bfs return if a graph is bipartition
def bfs(graph, u):
# if u is not visited, visit it and color it
# else do nothing and exit
if u not in visited:
visited.add(u)
colors[u] = 0
queue = [u]
while queue:
u = queue.pop(0)
# color the neighbors of u
for v in graph[u]:
# if v is not visited, visit, color and enqueue
if v not in visited:
visited.add(v)
colors[v] = 1 - colors[u]
queue.append(v)
else:
# if v is visited, check if the colors are different
if colors[v] == colors[u]:
return False
return True
# examine all nodes
for u in graph:
if not bfs(graph, u):
return False
return True
# test
N = 4
dislikes = [[1,2],[1,3],[2,4]]
print(possibleBipartition(N, dislikes))
N = 3
dislikes = [[1,2],[1,3],[2,3]]
print(possibleBipartition(N, dislikes))
True
False
# DFS
def possibleBipartition(N, dislikes):
# construct an undirected graph
graph = {}
for i in range(1, N+1):
graph[i] = []
for u, v in dislikes:
graph[u].append(v)
graph[v].append(u)
# color the graph using DFS
colors = {}
visited = set()
# dfs traverse the graph and return if a graph is bipartition
def dfs(graph, u, color):
visited.add(u)
colors[u] = color
for v in graph[u]:
if v not in visited:
dfs(graph, v, 1-color)
else:
if colors[v] == colors[u]:
return False
return True
# examine all nodes
for u in graph:
colors[u] = 0 if u not in colors else colors[u]
if not dfs(graph, u, colors[u]):
return False
return True
# test
N = 4
dislikes = [[1,2],[1,3],[2,4]]
print(possibleBipartition(N, dislikes))
N = 3
dislikes = [[1,2],[1,3],[2,3]]
print(possibleBipartition(N, dislikes))
True
False