不想码代码的时候就写博客……(每天
水写两篇)
# 题面
> Linked Codeforces 599E
点击展开/折叠代码
你曾经有一棵(以 $1$ 号点为根的)树,但你却忘记了它的形态,只记得其中的 $m$ 条边,以及 $q$ 对关系:$a_i$ 号点和 $b_i$ 号点的 LCA 为 $c_i$ 号点。现在你想知道有多少种满足这些条件的树。
# 解析
DP状态比较正常,$f_{u,S}$ 表示当前子树包含 $S$ 中的节点,根为 $u$。
转移则枚举 $S$ 的一个不包含 $u$ 的点集 $T$,但是为了避免算重(这里算重主要是因为 $u$ 的子树之间是无序的),我们需要固定 $S-\{u\}$ 中的编号最小点(当然也可以最大,反正要是一个唯一确定的点)在 $T$ 中。
> Tab. 下面用 $E$ 表示输入给定的边集
这样枚举出的 $T$ 并不一定满足限制,分析两个限制:
- 边的限制
- 若边的一端为 $u$,如果 $|\{v\mid (u,v)\in E\cap v\in T\}|\ge 2$,显然是不可能的,因为一棵子树中只可能有一个点与 $u$ 有边;
- 若边 $(a,b)$ 的两端都不为 $u$,如果 $a\in T\cap b\not\in T$ 也是不可能的;
- LCA 的限制
- 若 $\operatorname{LCA}(a,b)=u$,则 $a,b$ 不同时出现在 $T$ 中;
- 若 $\operatorname{LCA}(a,b)\in T$,则必须 $a,b\in T$;
满足以上限制就可以了。
对于边的限制,因为边数是 $O(n)$ 的,可以直接暴力枚举判断。
对于 LCA 的限制,直接枚举我觉得理论上过不了(但是事实说明它还是过了)。我就先处理出 ban[u][S]
和 alw[u]
:
- 当 $u$ 是当前子树的根时,若
ban[u][S]==true
则选取 $S$ 为子树的方案不可行,原因是存在 $a,b\in S$ 且 $\operatorname{LCA}(a,b)=u$; - 若存在 $u\in T$ 且
(alw[u]&T)!=alw[u]
,则选取 $T$ 为子树的方案是不合法的;因为若 $u\in T$,且 $\operatorname{LCA}(a,b)=u$ ,则必须 $a,b\in T$。
具体看看代码 awa
# 源代码
1 | /*Lucky_Glass*/ |