题目简介:
给定一组 n 人(编号为 1, 2, ..., n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。
给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 ai 和 bi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。
示例 1:
1 2 3
   | 输入:n = 4, dislikes = [[1,2],[1,3],[2,4]] 输出:true 解释:group1 [1,4], group2 [2,3]
   | 
 
示例 2:
1 2
   | 输入:n = 3, dislikes = [[1,2],[1,3],[2,3]] 输出:false
   | 
 
提示:
1 <= n <= 2000 
0 <= dislikes.length <= 10^4 
dislikes[i].length == 2 
1 <= dislikes[i][j] <= n 
ai < bi 
dislikes 中每一组都 不同 
思路:
使用并查集,初始化假设每个人只能和自己分到一起(每个人的祖先都是自己)。
然后依次遍历每个人不喜欢的人,若自己与不喜欢的人分到了一起(祖先相同),则返回false。
否则,将其不喜欢的人都分到同一组(祖先都为同一个)。
若最后无冲突,则返回true。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
   | class Solution { public:     bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
          vector<int> p(n + 1);         iota(p.begin(), p.end(), 0);    
          function<int(int)> find = [&](int x) -> int {             if (p[x] != x) p[x] = find(p[x]);             return p[x];         };
          vector<vector<int>> graph(n + 1, vector<int>());            for(int i = 0; i < dislikes.size(); i++){
              graph[dislikes[i][0]].push_back(dislikes[i][1]);             graph[dislikes[i][1]].push_back(dislikes[i][0]);         }
          for(int i = 0; i < n; i++){
              for(int j = 0; j < graph[i + 1].size(); j++){
                  if(find(i + 1) == find(graph[i + 1][j]))                         return false;                                  p[find(graph[i + 1][j])] = find(graph[i + 1][0]);                }         }
          return true;     } };
  |