二分图
https://leetcode-cn.com/problems/is-graph-bipartite/
存在一个 无向图 ,图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph ,其中 graph[u] 是一个节点数组,由节点 u 的邻接节点组成。形式上,对于 graph[u] 中的每个 v ,都存在一条位于节点 u 和节点 v 之间的无向边。该无向图同时具有以下属性:
不存在自环(graph[u] 不包含 u)。
不存在平行边(graph[u] 不包含重复值)。
如果 v 在 graph[u] 内,那么 u 也应该在 graph[v] 内(该图是无向图)
这个图可能不是连通图,也就是说两个节点 u 和 v 之间可能不存在一条连通彼此的路径。
二分图 定义:如果能将一个图的节点集合分割成两个独立的子集 A 和 B ,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,就将这个图称为 二分图 。
如果图是二分图,返回 true ;否则,返回 false 。
示例 1:
输入:graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
输出:false
解释:不能将节点分割成两个独立的子集,以使每条边都连通一个子集中的一个节点与另一个子集中的一个节点。
示例 2:
输入:graph = [[1,3],[0,2],[1,3],[0,2]]
输出:true
解释:可以将节点分成两组: {0, 2} 和 {1, 3} 。
提示:
graph.length == n
1 <= n <= 100
0 <= graph[u].length < n
0 <= graph[u][i] <= n - 1
graph[u] 不会包含 u
graph[u] 的所有值 互不相同
如果 graph[u] 包含 v,那么 graph[v] 也会包含 u
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/is-graph-bipartite
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二分图的定义
是可以将一个图中的顶点分割成两个子集
以使每条边都连通一个子集中的一个节点与另一个子集中的一个节点
问题转化
图着色问题
判断是否能够用两种颜色的着色方案
使得每条边连接的两点颜色不同
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class Solution{
public:
bool isBipartite(vector<vector<int> >& g){
vector<int> color(g.size(),-1); //每个点都有颜色
stack<int> color_stack;
for(int i = 0; i < g.size(); ++i){
if(color[i] == -1){
color_stack.push(i);
color[i] = 0;
while(!color_stack.empty()){
int index = color_stack.top();
color_stack.pop();
for(int j = 0; j < g[index].size(); ++j){
if(color[g[index][j]] == -1){//如果邻居结点没有染色
color[g[index][j]] = color[index] ^ 1;
color_stack.push(g[index][j]);
}
else{
if(color[g[index][j]] != (color[index]^1))
return false;
}
}
}
}
}
return true;
}
};
代码思路
首先
每个点都有初始颜色-1
然后
由于是dfs
所以需要一个栈来控制先进后出
然后
大体上是一个for循环嵌套一个while循环嵌套一个for循环
for循环控制dfs递归结束后访问其他的邻居结点
while循环控制dfs递归到栈为空
然后
栈的操作:
栈顶元素出栈
对栈顶元素的所有邻居:
如果没有颜色(-1)染色成和栈顶元素不一样的颜色,入栈
如果有颜色但是和栈顶元素一样,返回false,说明不能通过两种不同的颜色对图染色
总结
对于二分图
可以用广度优先遍历也可以用深度优先遍历
只用一开始用一种颜色,(0)
对于未染色的点,
染成不同的颜色,
对于已经染色的点,
如果颜色相同则一定不能只用两种颜色染图