新高一暑假第一期集训恢复性训练【数据结构-并查集】(补)
新高一暑假第一期集训恢复性训练【数据结构-并查集】(补)
C. [POJ1417] True Liars
先将题目中的好人和坏人转换一下,也即是如果 \(x\) 说 \(y\) 是好人,则他们两属于同一组,反之则不属于同一组。
然后我们可以想到带权的并查集,用 \(val_x\) 代表 \(x\) 与其父节点的关系,当 \(val_x\) 为 \(0\) 时 \(x\) 与其父亲同类,为 \(1\) 时不同类。由于这是一个传递的关系,所以会 \(\mod 2\)。
假定我们已经分好了类,那么就会有 \(n\) 个集合,每个集合有与父节点同类的,也有不同类的。
如果我们现在要确定出好人的数量,那么在每个集合里面只能选一种,这时就用 dp 来处理:设 \(f_{i, j}\) 的含义是处理到第 \(i\) 个集合时,和为 \(j\) 的方案总数。
那么初始化 \(f_{0, 0} = 1\),转移方程为 \(f_{i, j} = f_{i, j} + f_{i - 1, j - t_0/j - t_1}\),\(t_0\),\(t_1\) 为 \(i\) 集合中的两类的数量。
最后注意,如果 \(p1\) 等于 \(0\),也会输出一个 end。
E. [NOIP2023] 三值逻辑
赛场上没做出来的。甚至没有想到并查集
定义 \(T\) 对应 \(n + 1\),\(U\) 对应 \(n+2\),\(F\) 就是 \(-T\)。
这样我们就知道了每一个数代表着什么值,用 \(val\) 来表示。
设 \(T'\) 和 \(F'\) 两个数组分别记录这个数是不是 \(T\) 或者 \(F\)。
容易看出一般情况下 \(T'\) 和 \(F'\) 不会在一个并查集中,除非这个数是 \(U\)。
所以对于 \(i\) 我们考虑 \(val_i\) 是什么。
- 是 \(U\),那么直接合并 \(T'_i\) 和 \(F'_i\)。
- 是 \(T\),直接跳过。
- 是 \(x_j\),说明 \(x_i\) 和 \(x_j\) 一致,合并 \(T'_i\) 和 \(T'_j\) 以及 \(F'_i\) 和 \(F'_j\)。
- 是 \(-x_j\),说明 \(x_i\) 和 \(-x_j\) 一致,合并 \(T'_i\) 和 \(F'_j\) 以及 \(T'_j\) 和 \(F'_i\)。
最后判断有几对 \(T'_i\) 和 \(F'_i\) 在一个并查集里即可。
F. [CF1850H] The Third Letter
考虑把互相有直接或间接限制的点看作一棵树,加入到树中的结点是受到限制的。
最开始的状况没有限制,考虑逐个加入限制。最开始是一片森林,每棵树中只有一个结点,感觉很像并查集。
对于每个结点,我们维护它与自己祖先之间的相对距离,记录一个 \(d\)。并查集合并时,我们只需要更改它祖先的 \(d\)。
关于判无解,只需要考虑两个结点是否在同一个集合中以及距离是否与集合中的限制相等。
其他的就是普通的带权并查集操作。

浙公网安备 33010602011771号