Leetcode 785.判断二分图
题目:
存在一个 无向图 ,图中有 n n n 个节点。其中每个节点都有一个介于 0 0 0 到 n − 1 n - 1 n−1 之间的唯一编号。给你一个二维数组 g r a p h graph graph ,其中 g r a p h [ u ] graph[u] graph[u] 是一个节点数组,由节点 u u u 的邻接节点组成。形式上,对于 g r a p h [ u ] graph[u] graph[u] 中的每个 v v v ,都存在一条位于节点 u u u 和节点 v v v之间的无向边。该无向图同时具有以下属性:
- 不存在自环( g r a p h [ u ] graph[u] graph[u] 不包含 u u u)。
- 不存在平行边( g r a p h [ u ] graph[u] graph[u] 不包含重复值)。
- 如果 v v v 在 g r a p h [ u ] graph[u] graph[u] 内,那么 u u u 也应该在 g r a p h [ v ] graph[v] graph[v] 内(该图是无向图)
- 这个图可能不是连通图,也就是说两个节点 u u u 和 v v v 之间可能不存在一条连通彼此的路径。
二分图 定义:如果能将一个图的节点集合分割成两个独立的子集 A A A和 B B B ,并使图中的每一条边的两个节点一个来自 A A A集合,一个来自 B B 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} 。
提示:
- g r a p h . l e n g t h = = n graph.length == n graph.length==n
- 1 < = n < = 100 1 <= n <= 100 1<=n<=100
- 0 < = g r a p h [ u ] . l e n g t h < n 0 <= graph[u].length < n 0<=graph[u].length<n
- 0 < = g r a p h [ u ] [ i ] < = n − 1 0 <= graph[u][i] <= n - 1 0<=graph[u][i]<=n−1
- g r a p h [ u ] graph[u] graph[u] 不会包含 u u u
- g r a p h [ u ] graph[u] graph[u] 的所有值 互不相同
- 如果 g r a p h [ u ] graph[u] graph[u] 包含 v v v,那么 g r a p h [ v ] graph[v] graph[v] 也会包含 u u u
思路:
题目大意是能不能把图中的所有点分成两个部分,其中每个部分的点都不能一步到达,也就是没有直接相连的路径
也就是对于每一个点,它相邻的点只能在它的对面
如果每个点都能放进左右两边且不冲突
那么这个图就是二分图
我们使用一个数组来保存每个点在左边还是右边
循环枚举,遇到没有放的元素就把它加入左边,再循环把与它相连的结点放进右边
如果放完了所有节点都没有冲突,就返回 t r u e true true
遇到冲突(不能放的情况) 直接返回 f a l s e false false
代码:
class Solution {
public:
//记录每个点的位置 -1表示在左边 0表示还没有分配 1表示在右边
int left_or_right[110];
//把n结点放到左边 n节点的所有能一步到的点放到右边 不成功则返回false
bool left(int n, vector <vector<int>> &graph) {
for (int i = 0; i < graph[n].size(); i++) {
if (left_or_right[graph[n][i]] == -1) return false;
if (left_or_right[graph[n][i]] == 0) {
left_or_right[graph[n][i]] = 1;
if (!right(graph[n][i], graph)) return false;
}
}
return true;
}
//把n结点放到右边 n节点的所有能一步到的点放到左边 不成功则返回false
bool right(int n, vector <vector<int>> &graph) {
for (int i = 0; i < graph[n].size(); i++) {
if (left_or_right[graph[n][i]] == 1) return false;
if (left_or_right[graph[n][i]] == 0) {
left_or_right[graph[n][i]] = -1;
if (!left(graph[n][i], graph)) return false;
}
}
return true;
}
bool isBipartite(vector <vector<int>> &graph) {
int n = graph.size();
for (int i = 0; i <= n; i++) left_or_right[i] = 0;
for (int i = 0; i < n; i++) {
//遇到没有放的结点就把它放进左边
if (left_or_right[i] == 0) {
left_or_right[i] = -1;
if (!left(i, graph)) return false;
}
}
return true;
}
};