leetcode 785. 判断二分图
分析
如果给定的无向图连通,那么我们就可以任选一个节点开始,给它染成红色。随后我们对整个图进行遍历,将该节点直接相连的所有节点染成绿色,表示这些节点不能与起始节点属于同一个集合。我们再将这些绿色节点直接相连的所有节点染成红色,以此类推,直到无向图中的每个节点均被染色。
如果我们能够成功染色,那么红色和绿色的节点各属于一个集合,这个无向图就是一个二分图;如果我们未能成功染色,即在染色的过程中,某一时刻访问到了一个已经染色的节点,并且它的颜色与我们将要给它染上的颜色不相同,也就说明这个无向图不是一个二分图。
算法流程
-
我们任选一个节点开始,将其染成红色,并从该节点开始对整个无向图进行遍历;
-
在遍历的过程中,如果我们通过节点 uu 遍历到了节点 vv(即 uu 和 vv 在图中有一条边直接相连),那么会有两种情况:
- 如果 vv 未被染色,那么我们将其染成与 uu 不同的颜色,并对 vv 直接相连的节点进行遍历;
- 如果 vv 被染色,并且颜色与 uu 相同,那么说明给定的无向图不是二分图。我们可以直接退出遍历并返false
-
当遍历结束时,说明给定的无向图是二分图,返回true
实现
private static int WHITE = 0;
private static int RED = 1;
private static int GREEN = 2;
public boolean isBipartite(int[][] graph) {
int len = graph.length;
int[] colors = new int[len];
boolean tmpValid = true;
for(int i=0;i<graph.length;i++) {
//如果未染色,则进行染色
if(colors[i]==WHITE) {
tmpValid = isBipartite(graph,i,RED,colors,tmpValid);
}
}
return tmpValid;
}
/**
*深度遍历
*/
public boolean isBipartite(int[][] graph, int index, int color, int[] colors,boolean valid) {
//当前节点染色
colors[index] = color;
//子节点颜色
int nextColor = color==RED?GREEN:RED;
//遍历子节点
for(int i=0;i<graph[index].length;i++) {
int cIndex =graph[index][i];
//子节点未染色,则开始染色
if(colors[cIndex]==WHITE) {
//子节点未染色,则开始染色
valid = isBipartite(graph,cIndex,nextColor,colors,valid);
if(!valid) {
return valid;
}
}else if (colors[cIndex]!=nextColor) {
//子节已经染色,但和即将染的颜色不一致,说明非二分图
valid = false;
return valid;
}
}
return valid;
}