问题描述
给定一组
n
人(编号为1, 2, ..., n
), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。给定整数
n
和数组dislikes
,其中dislikes[i] = [ai, bi]
,表示不允许将编号为ai
和bi
的人归入同一组。当可以用这种方法将所有人分进两组时,返回true
;否则返回false
。
示例
示例 1:
输入:n = 4, dislikes = [[1,2],[1,3],[2,4]] 输出:true 解释:group1 [1,4], group2 [2,3]示例 2:
输入:n = 3, dislikes = [[1,2],[1,3],[2,3]] 输出:false示例 3:
输入:n = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]] 输出:false提示:
1 <= n <= 2000
0 <= dislikes.length <= 10^4
dislikes[i].length == 2
1 <= dislikes[i][j] <= n
ai < bi
dislikes
中每一组都 不同
问题分析:
二分图问题,从我学到的知识,应该主动将其理解成双色问题。就是用两种颜色来对图上色,如果最后能形成二分图,则满足题目要求。
代码如下:
class Solution {
public:bool possibleBipartition(int n, vector<vector<int>>& dislikes) {// 满足二分图的标志bool ok = true;// 对应节点的颜色,false和true代表两种颜色vector<bool> color(n + 1);// 是否访问过,也就是上过色vector<bool> visited(n + 1);// 邻接表建双向图 vector<vector<int>> G(n + 1, vector<int>());for(int i = 0; i < dislikes.size(); ++i){G[dislikes[i][0]].push_back(dislikes[i][1]);G[dislikes[i][1]].push_back(dislikes[i][0]);}// dfs遍历上色function<void(int)> traverse = [&](int v){if(!ok) return;visited[v] = true;for(int w : G[v]){// 没有上过色,上跟相邻节点不一样的颜色if(!visited[w]){color[w] = !color[v];traverse(w);}// 上过色了,如果颜色跟相邻节点颜色一样不满足二分图else{if(color[w] == color[v]){ok = false;return;}}}};for(int i = 1; i <= n; ++i){if(!visited[i]){traverse(i);}}return ok;}
};