1. 程式人生 > >LeetCode練習題785. Is Graph Bipartite?

LeetCode練習題785. Is Graph Bipartite?

題目

Given an undirected graph, return true if and only if it is bipartite.

Recall that a graph is bipartite 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.

The graph is given in the following form: graph[i]

is a list of indexes j for which the edge between nodes i and j exists.  Each node is an integer between 0 and graph.length - 1.  There are no self edges or parallel edges: graph[i] does not contain i, and it doesn't contain any element twice.

Example 1:
Input: [[1,3], [0,2], [1,3], [0,2]]
Output: true
Explanation:
The graph looks like this: 0----1 | | | | 3----2 We can divide the vertices into two groups: {0, 2} and {1, 3}.
Example 2:
Input: [[1,2,3], [0,2], [0,1,3], [0,2]]
Output: false
Explanation: 
The graph looks like this:
0----1
| \  |
|  \ |
3----2
We cannot find a way to divide the set of nodes into two independent subsets.

Note:

  • graph will have length in range [1, 100].
  • graph[i] will contain integers in range [0, graph.length - 1].
  • graph[i] will not contain i or duplicate values.
  • The graph is undirected: if any element j is in graph[i], then i will be in graph[j].

思路

這道題的大致意思是:給出一個無向圖,要我們判斷這個圖是否為二分圖。

首先我們要理解什麼是二分圖。二分圖又稱作二部圖,是圖論中的一種特殊模型。設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),並且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬於這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。

在弄清楚二分圖的定義後,我們可以利用一種簡單的方法來判斷一個圖是否為二分圖,即染色法。因為二分圖可以劃分為兩個互不相交的子集,所以可以只用兩種顏色染色,使得一條邊的兩個鄰接節點染上不同的顏色。

首先定義顏色,0為未上色,1為第一種顏色,-1為第二種顏色

大致做法:

  1. 宣告一個數組color,用來儲存所有點的顏色,全初始化為未上色,然後定義深度優先搜尋函式dfs,這個函式第一個引數是圖graph,第二個引數是要遍歷的開始點start,第三個引數是遍歷時開始點start的上一個點的顏色,第四個引數是所有點的顏色陣列color。
  2. 在dfs函式中,若此刻遍歷的開始點start的顏色為未上色,則染上與上一個鄰接點的顏色不同的顏色,然後繼續深度優先搜尋;若已上色,則判斷該點顏色是否與上一個鄰接點的顏色不同,若不同則返回true,否則返回false。
  3. 在isBipartite函式中,用for迴圈遍歷所有點,若該點是無顏色,則傳入深度優先搜尋函式dfs函式處理,否則跳過。(因為在一次dfs遍歷後,與開始點start連通的點肯定都進行了染色處理,所以已經染色的可以跳過。注意,此時傳入的點是第一個遍歷的點,不存在與之連線的上一個點的顏色,所以dfs函式的第三個引數我們預設傳入-1,目的是讓第一個遍歷的點染上第一種顏色。)

程式碼

class Solution {
public:
    bool dfs(vector<vector<int>>& graph, int start, int beforeColor, vector<int>& color) {
        if (color[start] != 0) {
            if (color[start] == beforeColor) return false;
            else return true;
        }

        color[start] = (-1) * beforeColor;
        int len = graph[start].size();
        for (int i = 0; i < len; i++) {
            if (dfs(graph, graph[start][i], color[start], color) == false) {
                return false;
            }
        }

        return true;
    }

    //染色法,二分圖最少只需兩種顏色區分兩個點集
    //一條邊對應的兩個點必須是不同的顏色
    bool isBipartite(vector<vector<int>>& graph) {
        int len = graph.size();
        vector<int> color;
        //初始化顏色,0為未上色,1為第一種顏色,-1為第二種顏色
        for (int i = 0; i < len; i++) {
            color.push_back(0);
        }

        for (int i = 0; i < len; i++) {
            if (color[i] == 0 && dfs(graph, i, -1, color) == false) {
                return false;
            }		
        }
        return true;
    }

};