判断二分图Java
文章发布较早,内容可能过时,阅读注意甄别。
# 题目
存在一个 无向图 ,图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph ,其中 graph[u] 是一个节点数组,由节点 u 的邻接节点组成。形式上,对于 graph[u] 中的每个 v ,都存在一条位于节点 u 和节点 v 之间的无向边。该无向图同时具有以下属性:
- 不存在自环(graph[u] 不包含 u)。
- 不存在平行边(graph[u] 不包含重复值)。
- 如果 v 在 graph[u] 内,那么 u 也应该在 graph[v] 内(该图是无向图)
- 这个图可能不是连通图,也就是说两个节点 u 和 v 之间可能不存在一条连通彼此的路径。
二分图 定义:如果能将一个图的节点集合分割成两个独立的子集 A 和 B ,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,就将这个图称为 二分图 。
如果图是二分图,返回 true ;否则,返回 false 。
示例 1:
输入:graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
输出:false
解释:不能将节点分割成两个独立的子集,以使每条边都连通一个子集中的一个节点与另一个子集中的一个节点。
示例 2:
输入:graph = [[1,3],[0,2],[1,3],[0,2]]
输出:true
解释:可以将节点分成两组: {0, 2} 和 {1, 3} 。
提示:
- graph.length == n
- 1 <= n <= 100
- 0 <= graph[u].length < n
- 0 <= graph[u][i] <= n - 1
- graph[u] 不会包含 u
- graph[u] 的所有值 互不相同
- 如果 graph[u] 包含 v,那么 graph[v] 也会包含 u
# 思路
dfs
# 解法
class Solution {
private boolean[] visited;
//每个顶点的颜色,0是蓝色,1是绿色
private int[] colors;
private int[][] graph;
public boolean isBipartite(int[][] graph) {
//将图放进类的成员变量中
this.graph = graph;
int V = graph.length;
visited = new boolean[V];
colors = new int[V];
/*对每一个联通分量进行检测,如果有一个联通分量不是二分图,
整个图就不是二分图*/
for(int v = 0; v < V; v ++)
if(!visited[v])
if(!dfs(v, 0)) return false;
return true;
}
//从v出发,检测是否满足二分图性质
private boolean dfs(int v, int color){
visited[v] = true;
//染色
colors[v] = color;
for(int w: graph[v]) {
//如果相邻顶点w没有被遍历过就要去遍历w并染色
if (!visited[w]) {
/*通过相邻顶点w检测到不是二分图了就返回false,
不需要再看其他相邻顶点了*/
if (!dfs(w, 1 - color)) return false;
}
/*如果相邻顶点遍历了而且颜色和当前这个顶点颜色一样,就不满足二分图性质
直接返回false,不需要再看其他相邻顶点了*/
else if (colors[v] == colors[w])
return false;
}
/*所有相邻顶点都检查了都没发现违反二分图性质,
就代表从当前v出发去检测满足二分图,返回true*/
return true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 总结
- 分析出几种情况,然后分别对各个情况实现