LeetCode練習題785. Is Graph Bipartite?
阿新 • • 發佈:2018-12-12
題目
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]
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 containi
or duplicate values.- The graph is undirected: if any element
j
is ingraph[i]
, theni
will be ingraph[j]
.
思路
這道題的大致意思是:給出一個無向圖,要我們判斷這個圖是否為二分圖。
首先我們要理解什麼是二分圖。二分圖又稱作二部圖,是圖論中的一種特殊模型。設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),並且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬於這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。
在弄清楚二分圖的定義後,我們可以利用一種簡單的方法來判斷一個圖是否為二分圖,即染色法。因為二分圖可以劃分為兩個互不相交的子集,所以可以只用兩種顏色染色,使得一條邊的兩個鄰接節點染上不同的顏色。
首先定義顏色,0為未上色,1為第一種顏色,-1為第二種顏色
大致做法:
- 宣告一個數組color,用來儲存所有點的顏色,全初始化為未上色,然後定義深度優先搜尋函式dfs,這個函式第一個引數是圖graph,第二個引數是要遍歷的開始點start,第三個引數是遍歷時開始點start的上一個點的顏色,第四個引數是所有點的顏色陣列color。
- 在dfs函式中,若此刻遍歷的開始點start的顏色為未上色,則染上與上一個鄰接點的顏色不同的顏色,然後繼續深度優先搜尋;若已上色,則判斷該點顏色是否與上一個鄰接點的顏色不同,若不同則返回true,否則返回false。
- 在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;
}
};