LeetCode Bipartition Graph Related Problems

LC886 Possible Bipartition
we are given int N, int[][] dislikes.
so N represent the number of vertices we have. and dislike[i] = [2,3] represents for there s no edge between node2 and node3.
we need to check if the given graph is bipartition or not.

idea:
let’s assume the group a person belongs is either 1 or -1. so starting from any node and we use dfs/bfs to tranverse the whole graph(why do we have to starting from every node? because we know that this graph is possibly not One graph), and on our way to tranverse other node, we assign this node with group number(1 or -1), when we find a node is “dislike” by two both people from group1 and -1, then dfs/bfs fails.
and if the graph is only one connected graph, then we should return false as well.

class Solution {
    public boolean possibleBipartition(int N, int[][] dislikes) {
        List<Integer>[] graph = new ArrayList[N]; //graph is [list1, list2, list3...]
        for (int i = 0; i < N; i++) graph[i] = new ArrayList<>(N); //initialize each one of them, it is not necessary
        for (int i = 0; i < dislikes.length; i++) {
            int a = dislikes[i][0] - 1; //project input to graph we can easily use
            int b = dislikes[i][1] - 1;
            graph[a].add(b);
            graph[b].add(a);
        }
        int[] color = new int[N];
        color[0] = 1;
        for (int i = 0; i < N; i++) {
            if (!dfs(graph, i, color)) return false;
        }
        return true;   
    }
    
    private boolean dfs(List<Integer>[] graph, int node, int[] color) {
        for (int i = 0; i < graph[node].size(); i++) { //for every neighbor of current node
            int op = graph[node].get(i); 
            if (color[op] == 0) { //if it is either 1 or -1
                color[op] = color[node] == 1 ? 2 : 1; //then 
                if (!dfs(graph, op, color)) return false;
            } else {
                if (color[op] == color[node]) return false;
            }
        }
        return true;
    }
}

LeetCode785 is Graph bipartite?
check if a graph is bipartite, and this is little different from previous problem, because the defination of bipartite is if we can split it’s set of nodes into two independent subsets A and B such that every edge in the graph has one node in A and another node in B.
so we have to check every edge and we have to make sure each edge has one end that belongs to set1 and the other belongs to set2. if any edge is not this situation, then we can only return false.
so the general idea is: we will trying to use two colors to color the graph and see if there are any adjacent nodes having the same color.
so there are two colors to choose, which we will initialize the int[] color will all 0, and 1 will represent blue and -1 will represent red.

so we do dfs for each node, and for each node along the path, we have two situations:

  1. if the node hasn’t been colored, the choose a color which is different than its precious level to paint it.
  2. if it has been colored, check the color to see if it is the color we are gonna use if current node is not colored.

the dfs version of code:

class Solution {
    public boolean isBipartite(int[][] graph) {
        int n = graph.length;
        int[] colors = new int[n];			
				
        for (int i = 0; i < n; i++) {              //This graph might be a disconnected graph. So check each unvisited node.
            if (colors[i] == 0 && !dfs(graph, colors, 1, i)) { //we check if current node has colors on it or not. only when it haven't painted did we check the dfs, and for all the node that is already painted, we do nothing.
                return false; //if there is one that can't have a successful dfs, then return false
            }
        }
        return true;
    }
    
    public boolean dfs(int[][] graph, int[] colors, int color, int node) { //we dfs is successful, then we return true
        if (colors[node] != 0) {
            return colors[node] == color;
        }       
        colors[node] = color;       
        for (int next : graph[node]) { //for every neighbor
            if (!dfs(graph, colors, -color, next)) { //dfs all the way down, if any of them is can't succeed, then we return false, pay attention to the way it changes color: by -color
                return false;
            }
        }
        return true;
    }
}

and the following is the bfs version:
just use a normal bfs, we can only starting from any node(not each of them) and starting our bfs. check every next node with those two situations we discussed before.

class Solution {
    public boolean isBipartite(int[][] graph) {
        int len = graph.length;
        int[] colors = new int[len];
        
        for (int i = 0; i < len; i++) {
            if (colors[i] != 0) continue;
            Queue<Integer> queue = new LinkedList<>(); //use queue, that's just classic
            queue.offer(i);
            colors[i] = 1;   // Blue: 1; Red: -1.
            
            while (!queue.isEmpty()) {
                int cur = queue.poll();
                for (int next : graph[cur]) {
                    if (colors[next] == 0) {          // If this node hasn't been colored;
                        colors[next] = -colors[cur];  // Color it with a different color;
                        queue.offer(next);
                    } else if (colors[next] != -colors[cur]) {   // If it is colored and its color is different than we expected(which is -color[cur]), then return false;
                        return false;
                    }
                }
            }
        }
        
        return true; 
    }
}
posted @ 2020-05-31 09:14  EvanMeetTheWorld  阅读(16)  评论(0)    收藏  举报