判断二分图

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;
}
posted @ 2020-07-16 13:46  zincredible  阅读(167)  评论(0编辑  收藏  举报