LeetCode 可能的二分法(深度优先搜索)

给定一组 N 人(编号为 1, 2, …, N), 我们想把每个人分进任意大小的两组。

每个人都可能不喜欢其他人,那么他们不应该属于同一组。

形式上,如果 dislikes[i] = [a, b],表示不允许将编号为 a 和 b 的人归入同一组。

当可以用这种方法将每个人分进两组时,返回 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 <= 10000
1 <= dislikes[i][j] <= N
dislikes[i][0] < dislikes[i][1]
对于 dislikes[i] == dislikes[j] 不存在 i != j 

思 路 分 析 : \color{blue}思路分析: 这道题有点类似染色问题,首先我们需要对dislikes容器进行处理,转换为vector> myDisLike(N + 1);,myDislike[i]存储i不喜欢的所有人。(类似图中的邻接表)

接着我们从dislikes[i]开始,如果dislikes[i][0]没有确定分组,则将它默认分组为0,将dislikes[i][1]分组为1(myDislike[i]中的所有人都需要分组1,myDislike[i]存储i讨厌的所有人)。如果在深度优先搜索的时候出现某个人与他不喜欢的人在一个分组,则直接返回false。

如果所有人都分配完成后都没有出现false,则说明能进行二分。

还有一点,可能有些道友认为默认分组为0可能会影响,为啥不默认分组为1呢?
假设能分成两个组0,1,它们各自不冲突,那可不可以把0组所有人换到1,把1组所有人换到0?
所有,如果它本身能分组,默认分0还是1是没有关系的。

class Solution {
public:
    bool possibleBipartition(int N, vector<vector<int>>& dislikes) {
        if (dislikes.empty()){
            return true;
        }
        vector<int> resPartition(N + 1, -1);//resPartition[i]记录着i的分组,分组只有0,1,初始化为-1,说明是还没有分组
        vector<vector<int>> myDisLike(N + 1);//myDisLike[i]记录这i所有的不喜欢的人
        //将dislikes容器转换为myDisLike容器信息
        for (const auto & dislike : dislikes){
            myDisLike[dislike[0]].push_back(dislike[1]);
            myDisLike[dislike[1]].push_back(dislike[0]);
        }
        //对所有的dislikes对进行处理
        for (const auto & dislike : dislikes){
            //检查这个不喜欢对是否处理过了
            if (resPartition[dislike[0]] == -1){
                //如果没有处理过,则将dislike[0]分组默认为 0
                if (!dfs(myDisLike, dislike[0], 0, resPartition)){
                    return false;
                }
            }
        }
        return true;
    }
    //在person分组为partition的情况下,确定他不喜欢的人的分组,返回false说明出现了冲突
    bool dfs(vector<vector<int>> &myDisLike, int person, int partition, vector<int> &resPartition){
        if (resPartition[person] == -1){
            //如果person还未分组,则分为partition
            resPartition[person] = partition;
            //则person不喜欢的所有人都应该分组为 !partition
            for (const auto dislikePerson : myDisLike[person]){
                if (resPartition[dislikePerson] == resPartition[person]){
                    //如果person和他不喜欢的dislikePerson已经在一个组
                    return false;
                }
                //深度优先处理,在dislikePerson分组!partition情况下,确定dislikePerson所不喜欢的人的分组
                if (!dfs(myDisLike, dislikePerson, !partition, resPartition)){
                    return false;
                }
            }
            return true;
        }
        else if (resPartition[person] != partition){
            //如果person应该分组partition,蛋式他出现在对立组,冲突
            return false;
        }
        return true;
    }
};

LeetCode 可能的二分法(深度优先搜索)_第1张图片

你可能感兴趣的:(LeetCode,深度,广度优先搜索)