技巧
带权并查集
思路
通过权重来类比元素之间的关系
路径压缩的地方做文章
如果之前两个元素在一个集合中,就通过两个权值判断相互关系验证真假
如果没有关系怎么说都是真的 需要建立关系
实现
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) }