题目大意
将N个人划分为两组,每个人可能不喜欢其他人,即不能和不喜欢的分到一组,问是否能够成功划分。
输入
N
和dislike[][2]
分别表示人的个数和不喜欢的列表。例如N = 4, dislikes = [[1,2],[1,3],[2,4]]
,表示4个人,其中1与2,1与3,2与4不能分到同一组。
思路
类似并查集,因为不喜欢是成对出现的,所以记录每个元素所属的集合
以及不喜欢的集合
。对于不喜欢列表中的每一对(x, y)
,如若
- x,y都未加入任何集合 - 以他们自己为根元素初始化两个新集合,且x的
不喜欢集合
为y,y的不喜欢集合
为x - y未加入任何集合,x属于某个集合
rootx
- 将y加入到x的不喜欢集合
中,将y的不喜欢集合
设置为x - x未加入任何集合,y属于某个集合
rooty
- 同上,将x加入到y的不喜欢集合,将x的不喜欢集合设置为y - x,y都加入了某个集合
rootx,rooty
- 若rootx==rooty
,则return false
,无法划分
若最后一种情况未出现,则表示可以划分为两个集合
代码
struct T{
int root, oproot;
T(){ root = oproot = -1;}
bool empty() { return root == -1; }
void setRoot(int root, int oproot) { this->root = root, this->oproot = oproot; }
};
class Solution {
public:
bool possibleBipartition(int N, vector<vector<int>>& dislikes) {
vector<T> roots(N + 1);
for (auto tmpvec: dislikes) {
int x = tmpvec[0], y = tmpvec[1];
T &xt = roots[x], &yt = roots[y];
if (xt.empty() && yt.empty()) {
xt.setRoot(x, y);
yt.setRoot(y, x);
} else if (xt.empty()) {
xt.setRoot(yt.oproot, yt.root);
} else if (yt.empty()){
yt.setRoot(xt.oproot, xt.root);
} else {
if (xt.root == yt.root) return false;
}
}
return true;
}
};
总结
讨论版中有以二分图为思路使用BFS进行红蓝着色的,感兴趣的可以参考这里。