题目:
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.j
is in graph[i]
, then i
will be in graph[j]
.思路:
我们可以将这个图问题转换成为染色问题:如果这个图是二分图,那么它必然可以被二着色。所以我们每次遇到一个结点时,首先检查它是否已经被着色;如果是,则看是否和前面的着色相兼容;如果是则继续,否则就说明该图不是二分图,返回false。这种图的遍历问题一般既可以用BFS也可以用DFS,下面我们分别给出两种方法的解释和源代码。
1、BFS:逐个检查每个节点是否已经被染色,如果没有被染色,则首先将其染为颜色0,然后采用BFS依次对和它相连的节点进行检查和染色。如果相连的节点没有被染色,则将其染为另外一种颜色;否则就检查染色是否和原来兼容,如果不兼容则立即返回false。注意当从一个结点开始的的BFS搜索全部结束时,和该结点有直接或者间接连接关系的所有结点都会已经被染色了,所以当开始对下一个节点染色的时候,我们就可以大胆将其染为颜色0。这样当整个染色完成的时候,如果没有发现染色冲突,则说明原来的图就是二分图。
2、DFS:思路其实和BFS非常一致,只不过采用了DFS的搜索策略:首先检查该结点是否已经被染色,如果是,则返回其是否兼容的信息;否则就给结点染色,并且采用DFS的策略对和其直接或者间接相连的所有结点染色。整个过程中如果发现冲突就提前返回false;否则在最后返回true。
代码:
1、BFS:
class Solution {
public:
bool isBipartite(vector>& graph) {
int n = graph.size();
vector colors(n, -1);
for (int i = 0; i < n; ++i) {
if (colors[i] == -1) { // the node i has not been colored, so color it
if (!BFS(graph, colors, 0, i)) {
return false;
}
}
}
return true;
}
private:
bool BFS(vector> &graph, vector &colors, int color, int node) {
queue q;
q.push(node);
colors[node] = color;
while (!q.empty()) {
int i = q.front(), c = colors[i];
q.pop();
for (auto next : graph[i]) {
if (colors[next] == -1) { // not colored, so color it using another color
q.push(next);
colors[next] = 1 - c;
}
else { // already colored, so check whether it is compatible
if (colors[next] != 1 - c) {
return false;
}
}
}
}
return true;
}
};
class Solution {
public:
bool isBipartite(vector>& graph) {
int n = graph.size();
vector colors(n, -1); // colors[i] == -1 mean has not been colored
for (int i = 0; i < n; ++i) { // try to color this the i-th node
if (colors[i] == -1 && !DFS(graph, colors, 0, i)) {
return false;
}
}
return true;
}
private:
bool DFS(vector> &graph, vector &colors, int color, int node) {
if (colors[node] != -1) { // has been colored, so check whether compatible
return colors[node] == color;
}
colors[node] = color; // color the first node
for (int next : graph[node]) { // color other nodes who are connected with node
if (!DFS(graph, colors, 1 - color, next)) {
return false;
}
}
return true;
}
};