1.题目
https://leetcode-cn.com/problems/is-graph-bipartite/
给定一个无向图graph
,当这个图为二分图时返回true
。
如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。
graph
将会以邻接表方式给出,graph[i]
表示图中与节点i
相连的所有节点。每个节点都是一个在0
到graph.length-1
之间的整数。这图中没有自环和平行边: graph[i]
中不存在i
,并且graph[i]
中没有重复的值。
示例 1:
输入: [[1,3], [0,2], [1,3], [0,2]]
输出: true
解释:
无向图如下:
0----1
| |
| |
3----2
我们可以将节点分成两组: {0, 2} 和 {1, 3}。
示例 2:
输入: [[1,2,3], [0,2], [0,1,3], [0,2]]
输出: false
解释:
无向图如下:
0----1
| \ |
| \ |
3----2
我们不能将节点分割成两个独立的子集。
注意:
graph
的长度范围为[1, 100]
。graph[i]
中的元素的范围为[0, graph.length - 1]
。graph[i]
不会包含i
或者有重复的值。- 图是无向的: 如果
j
在graph[i]
里边, 那么i
也会在graph[j]
里边。
2.想法
对于图的操作不熟悉,还没有想法。
3.解法
3.1广度优先搜索
import collections
# bfs
class Solution(object):
def isBipartite(self, graph):
"""
:type graph: List[List[int]]
:rtype: bool
"""
size = len(graph)
# 定义 visited 数组,初始值为 0 表示未被访问,赋值为 1 或者 -1 表示两种不同的颜色
visited = [0 for _ in range(size)]
# // 因为图中可能含有多个连通域,所以我们需要判断是否存在顶点未被访问,若存在则从它开始再进行一轮 bfs 染色。
for i in range(size):
if visited[i] != 0:
continue
# 入队
q = collections.deque([i])
visited[i] = 1
while q:
v = q.popleft()
for w in graph[v]:
if visited[w] == visited[v]:
return False
if visited[w] == 0:
visited[w] = -visited[v]
q.append(w)
return True
3.2深度优先搜索
class Solution(object):
def isBipartite(self, graph):
"""
:type graph: List[List[int]]
:rtype: bool
"""
size = len(graph)
# 定义 visited 数组,初始值为 0 表示未被访问,赋值为 1 或者 -1 表示两种不同的颜色
visited = [0 for _ in range(size)]
# // 因为图中可能含有多个连通域,所以我们需要判断是否存在顶点未被访问,若存在则从它开始再进行一轮 bfs 染色。
for i in range(size):
if visited[i]==0 and (not self.dfs(graph,i,1,visited)):
return False
return True
def dfs(self, graph, v, color, visited):
#// 如果要对某顶点染色时,发现它已经被染色了,则判断它的颜色是否与本次要染的颜色相同,如果矛盾,说明此无向图无法被正确染色,返回 false。
if visited[v]!=0:
return visited[v]==color
#染色
visited[v]=color
for w in graph[v]:
if (not self.dfs(graph,w,-color,visited)):
return False
return True
3.3并查集
class Solution(object):
def isBipartite(self, graph):
"""
:type graph: List[List[int]]
:rtype: bool
"""
size=len(graph)
uf = UnionFind(size)
for i in range(size):
adjs = graph[i]
for w in adjs:
if uf.isConnected(i, w):
return False
uf.union(adjs[0], w)
return True
class UnionFind():
def __init__(self, n):
self.roots = [i for i in range(n)]
print(self.roots)
def find(self, i):
if self.roots[i] == i:
return i
self.roots[i]=self.find(self.roots[i])
return self.roots[i]
def isConnected(self, p, q):
return self.find(q) == self.find(p)
def union(self, p, q):
self.roots[self.find(p)] = self.find(q)