1. 程式人生 > 實用技巧 >leetcode 785: 判斷二分圖

leetcode 785: 判斷二分圖

package com.example.lettcode.dailyexercises;

/**
 * @Class IsBipartite
 * @Description 785 判斷二分圖
 * 給定一個無向圖graph,當這個圖為二分圖時返回true。
 * 如果我們能將一個圖的節點集合分割成兩個獨立的子集A和B,
 * 並使圖中的每一條邊的兩個節點一個來自A集合,一個來自B集合,我們就將這個圖稱為二分圖。
 * graph將會以鄰接表方式給出,graph[i]表示圖中與節點i相連的所有節點。
 * 每個節點都是一個在0到graph.length-1之間的整數。
 * 這圖中沒有自環和平行邊: graph[i] 中不存在i,並且graph[i]中沒有重複的值。
 * <p>
 * 示例 1:
 * 輸入: [[1,3], [0,2], [1,3], [0,2]]
 * 輸出: true
 * 解釋:
 * 無向圖如下:
 * 0----1
 * |    |
 * |    |
 * 3----2
 * 我們可以將節點分成兩組: {0, 2} 和 {1, 3}。
 * <p>
 * 示例 2:
 * 輸入: [[1,2,3], [0,2], [0,1,3], [0,2]]
 * 輸出: false
 * 解釋:
 * 無向圖如下:
 * 0----1
 * | \  |
 * |  \ |
 * 3----2
 * 我們不能將節點分割成兩個獨立的子集。
 * <p>
 * 注意:
 * graph 的長度範圍為 [1, 100]。
 * graph[i] 中的元素的範圍為 [0, graph.length - 1]。
 * graph[i] 不會包含 i 或者有重複的值。
 * 圖是無向的: 如果j 在 graph[i]裡邊, 那麼 i 也會在 graph[j]裡邊。
 * @Author
 * @Date 2020/7/16
 **/
public class IsBipartite {

    // visited 表示染色情況
    // 0表示未染色,1表示染黑色,-1表示染白色
    static int[] visited = new int[101];  // graph 的長度範圍是[1,100]

    /**
     * 利用染色演算法:以有邊的某頂點v0為起始位置,將其染色,與其相連的鄰接頂點染上另一種顏色,鄰接點的鄰接點染上與起始頂點v0
     * 相同的顏色,以此類推,直到所有以v0作為起始點所能到達的所有頂點都染上顏色
     * v0作為起始頂點時不一定能到達圖的全部頂點,所以還需要遍歷一遍全部頂點,重複上述步驟,直到所有頂點都被染色
     * 如何判斷是否為二分圖:當某頂點Vi染色時,其鄰接點已染色並且具有與Vi相同的顏色時,說明不是二分圖
     */
    public  static boolean isBipartite(int[][] graph) {
        if (graph == null || graph.length == 0) return false;

        int len = graph.length;
        for (int i = 0; i < len; i++) {
            // 未染色且非獨立點
            if (visited[i] == 0 && graph[i].length != 0) {
                visited[i] = 1; // 染成黑色
                for (int j = 0; j < graph[i].length; j++) {
                    // 鄰接點染白色
                    visited[graph[i][j]] = -1;
                    // 對graph[i][j]的鄰接點遞迴染色
                    boolean flag = dfs(graph, graph[i][j]);
                    if (flag == false) return false;
                }
            }
        }
        return true;
    }

    public static  boolean dfs(int[][] graph, int num) {
        boolean flag = true;   // ????
        // graph[num]表示圖中與節點num相連的所有節點
        for (int i = 0; i < graph[num].length; i++) {
            // 如果已染色並且和num節點的顏色相同,說明不是二分圖
            if (visited[num] == visited[graph[num][i]]) return false;
            // 如果未染色,則染成和num節點不同的顏色
            if (visited[graph[num][i]] == 0) {
                visited[graph[num][i]] = -visited[num];
                flag = dfs(graph, graph[num][i]);
            }
        }
        return flag;
    }

    public static void main(String[] args) {
        int[][] graph = new int[][]{{1,3}, {0,2}, {1,3}, {0,2}};
        boolean ans = isBipartite(graph);
        System.out.println("IsBipartite demo01 result:" + ans);
    }
}