演算法分析week3 | 785. Is Graph Bipartite?
阿新 • • 發佈:2018-12-11
目錄
- 題目描述
- 解題過程
- 完整程式碼
題目描述
解題過程
這道題與書上習題3.7類似。二部圖是這樣的圖G=(V,E),其頂點集合可以被劃分為兩個子集(V = V1 ∪ V2 且 V1 ∩ V2 = Ф),並且子集內部的頂點之間沒有邊相連。
要判斷一個無向圖是否是二部圖,我們可以考慮這個圖是否可以用兩種顏色為它著色,有邊相連的兩個頂點需要著不同顏色。
首先,用一個數組subsets來記錄每個頂點的顏色,-1表示未著色,而0,1分別表示兩種不同的顏色。
vector<int> subsets; for(int i = 0; i < graph.size(); i++) subsets.push_back(-1);
由於給定的圖可能由多個強連通部件構成,因此需要對每個頂點進行檢查。如果當前頂點已經著色,則可以跳過,因為這表示該頂點所在的強連通部件已經被著色了。如果有一個強連通部件不能用兩種顏色著色,則返回false,如果所有強連通部件都可以用兩種顏色著色,則返回true。
for(int i = 0; i < graph.size(); i++) {
if(subsets[i] != -1) continue;
if(!explore(subsets, graph, i)) return false;
}
explore使用深度優先遍歷
bool explore(vector<int>& subsets, vector<vector<int>>& graph, int i) { if(subsets[i] == -1) subsets[i] = 0; for(int j = 0; j < graph[i].size(); j++) { if(subsets[graph[i][j]] != -1) { if(subsets[graph[i][j]] == subsets[i]) return false; continue; } subsets[graph[i][j]] = !subsets[i]; if(graph[graph[i][j]].size() > 0) { if(!explore(subsets, graph, graph[i][j])) return false; } } return true; }
這是個線性時間演算法,複雜度為O(V+E)。
完整程式碼
class Solution {
public:
bool isBipartite(vector<vector<int>>& graph) {
vector<int> subsets;
for(int i = 0; i < graph.size(); i++) subsets.push_back(-1);
for(int i = 0; i < graph.size(); i++) {
if(subsets[i] != -1) continue;
if(!explore(subsets, graph, i)) return false;
}
return true;
}
bool explore(vector<int>& subsets, vector<vector<int>>& graph, int i) {
if(subsets[i] == -1) subsets[i] = 0;
for(int j = 0; j < graph[i].size(); j++) {
if(subsets[graph[i][j]] != -1) {
if(subsets[graph[i][j]] == subsets[i]) return false;
continue;
}
subsets[graph[i][j]] = !subsets[i];
if(graph[graph[i][j]].size() > 0) {
if(!explore(subsets, graph, graph[i][j])) return false;
}
}
return true;
}
};