0886. 可能的二分法
大约 2 分钟
---
0886. 可能的二分法
- 标签:深度优先搜索、广度优先搜索、并查集、图
- 难度:中等
题目链接
题目大意
把 n 个人(编号为 1, 2, ... , n)分为任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。
给定表示不喜欢关系的数组 dislikes,其中 dislikes[i] = [a, b] 表示 a 和 b 互相不喜欢,不允许将编号 a 和 b 的人归入同一组。
要求:如果可以以这种方式将所有人分为两组,则返回 True;如果不能则返回 False。
解题思路
先构建图,对于 dislikes[i] = [a, b],在节点 a 和 b 之间建立一条无向边,然后判断该图是否为二分图。具体做法如下:
- 找到一个没有染色的节点
u,将其染成红色。 - 然后遍历该节点直接相连的节点
v,如果该节点没有被染色,则将该节点直接相连的节点染成蓝色,表示两个节点不是同一集合。如果该节点已经被染色并且颜色跟u一样,则说明该图不是二分图,直接返回False。 - 从上面染成蓝色的节点
v出发,遍历该节点直接相连的节点。。。依次类推的递归下去。 - 如果所有节点都顺利染上色,则说明该图为二分图,可以将所有人分为两组,返回
True。否则,如果在途中不能顺利染色,不能将所有人分为两组,则返回False。
代码
class Solution:
def dfs(self, graph, colors, i, color):
colors[i] = color
for j in graph[i]:
if colors[j] == colors[i]:
return False
if colors[j] == 0 and not self.dfs(graph, colors, j, -color):
return False
return True
def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
graph = [[] for _ in range(n + 1)]
colors = [0 for _ in range(n + 1)]
for x, y in dislikes:
graph[x].append(y)
graph[y].append(x)
for i in range(1, n + 1):
if colors[i] == 0 and not self.dfs(graph, colors, i, 1):
return False
return True