技巧
带权并查集
思路
通过权重来类比元素之间的关系
路径压缩的地方做文章
如果之前两个元素在一个集合中,就通过两个权值判断相互关系验证真假
如果没有关系怎么说都是真的 需要建立关系
实现
package main
import (
"bufio"
. "fmt"
"io"
"os"
)
// 带权并查集节点
type Animal struct {
id int
weight int
father *Animal
}
// 压缩路径(更新权值)
func getRoot(x *Animal) *Animal {
if x.father == nil {
return x
}
father := x.father
root := getRoot(x.father)
x.weight = (x.weight + father.weight) % 3
x.father = root
return root
}
func same(x, y *Animal) bool {
return getRoot(x) == getRoot(y)
}
// https://ac.nowcoder.com/acm/problem/16884
func NC16884(_r io.Reader, _w io.Writer) {
in, out := bufio.NewReader(_r), bufio.NewWriter(_w)
defer out.Flush()
var N, K int
Fscan(in, &N, &K)
// 构建并查集
set := make(map[int]*Animal)
for i := 1; i <= N; i++ {
set[i] = &Animal{i, 0, nil}
}
var fakeCnt int
for i := 0; i < K; i++ {
var D, X, Y int
Fscan(in, &D, &X, &Y)
// 当前的话中X或Y比N大,就是假话; 当前的话表示X吃X,就是假话。
if X > N || Y > N || (D == 2 && X == Y) {
fakeCnt++
} else if same(set[X], set[Y]) { // 验证合理性
xw, yw := set[X].weight, set[Y].weight
if D == 1 && set[X].weight == set[Y].weight {
continue
} else if D == 2 && ((xw == 0 && yw == 1) || (xw == 1 && yw == 2) || (xw == 2 && yw == 0)) {
continue
}
fakeCnt++
} else { // 建立关联
xr, yr := getRoot(set[X]), getRoot(set[Y])
yr.father = xr
yr.weight = (3 + set[X].weight + (D - 1) - set[Y].weight) % 3
}
}
Fprintln(out, fakeCnt)
}
func main() {
NC16884(os.Stdin, os.Stdout)
}

京公网安备 11010502036488号