题目:
给定一组 n 人(编号为 1, 2, ..., n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。
给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 ai 和 bi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。
算法:
方法一: dfs
统计每个人所有不喜欢的节点,然后dfs对节点进行染色,如果出现染色冲突(已染色为1,当前dfs又染色为2),则说明存在冲突。
func possibleBipartition(n int, dislikes [][]int) bool {
// 初始化不喜欢数组
dislikes2 := make([][]int, n)
for i := range dislikes {
x, y := dislikes[i][0] - 1, dislikes[i][1] - 1
dislikes2[x] = append(dislikes2[x], y)
dislikes2[y] = append(dislikes2[y], x)
}
peopleColors := make([]int, n)
// 将节点i 染色为color
var dfs func (i, color int) bool
dfs = func (i, color int) bool {
peopleColors[i] = color
for _, people := range dislikes2[i] {
if peopleColors[people] == color {
return false
}
if peopleColors[people] == 0 && !dfs(people, 3 - color) {
return false
}
}
return true
}
for i := range dislikes2 {
if peopleColors[i] == 0 && !dfs(i, 1) {
return false
}
}
return true
}
方法二:bfs
初始化color数组,保存每个人的颜色,0未染色,1红色,2蓝色
初始化数组g保存每个人不喜欢的所有人。
遍历g,将不喜欢的人染成对立颜色,如果发现不喜欢的人和自己是同一颜色,存在冲突
func possibleBipartition(n int, dislikes [][]int) bool {
color := make([]int, n)
g := make([][]int, n)
for i := range dislikes {
x, y := dislikes[i][0] - 1, dislikes[i][1] - 1
g[x] = append(g[x], y)
g[y] = append(g[y], x)
}
// 用栈stack代替了递归,本质上还是要递归染色
// q出栈了意味着他不喜欢的人的链,递归完了
for i := range color {
if color[i] == 0 {
color[i] = 1
stack := []int{i}
for len(stack) != 0 {
q := stack[0]
stack = stack[1:]
for _, j := range g[q] {
if color[j] == color[q] {
return false
}
if color[j] == 0 {
color[j] = 3 - color[q]
stack = append(stack, j)
}
}
}
}
}
return true
}
方法三:并查集
思路:将一个人不喜欢的所有人放到同一个联通分量,如果这个人也在这个联通分量中,则说明出现冲突。
func possibleBipartition(n int, dislikes [][]int) bool {
parent := make([]int, n)
g := make([][]int, n)
for i := range dislikes {
x, y := dislikes[i][0] - 1, dislikes[i][1] - 1
g[x] = append(g[x], y)
g[y] = append(g[y], x)
}
for i := range parent{
parent[i] = i
}
var find func(x int) int
find = func(x int) int {
if parent[x] != x {
parent[x] = find(parent[x])
}
return parent[x]
}
for i := range g {
for _, j := range g[i] {
if find(i) == find(j) {
return false
}
parent[find(j)] = find(g[i][0])
}
}
return true
}