题解 P7752 [COCI2013-2014#2] PALETA
洛谷。
题意
一共有 $n$ 个图像,可以染成 $k$ 种颜色。同时,每个图像有一个数字 $f_i$,若 $f_i\ne i$,则 $i$ 不能与 $f_i$ 同色;若 $f_i=i$,对于 $i$,可以选任何颜色。
分析
首先把每一个 $f$ 转化成边,即 $f_i$ 与 $i$ 连一条边,那么一共有 $n$ 条边,整个图就变成了一个基环树森林。
那么我们的整个计算就可以分成两类:一个是链上的,另一个是环上的(包括自环)。
对于链上的,由于我们是拓扑计算,因此,我们只需要考虑其对于父亲的影响,由于其与其父亲不同,因此我们这个节点一共有 $k-1$ 种选法。
while(!q.empty()) {
int now=q.front();
q.pop();
vis[now]=1;
val[fa[now]]=1ll*val[fa[now]]*val[now]%MOD*(m-1)%MOD;//m即k
if(!(--d[fa[now]])) q.push(fa[now]);
}
接下来的就是环上的计算,我们先拆环成链,那么最后的方案数可以转化成最后一个节点与第一个节点颜色不同的方案数,简单 DP 即可。
令 $f_{i,0}$ 表示第 $i$ 位与第一位选择一样的方案数,$f_{i,1}$ 表示第 $i$ 位与第一位选择不样的方案数。
那么很容易写出递推式:
$f_{i,0}=f_{i-1,1}$;
$f_{i,1}=f_{i-1,1}\times (k-2)+f_{i-1,0}\times (k-1)$。
至于每一个节点转移上来的选法全部累乘即可。
但是这题完结了吗?并没有,将我们上述的所有块代码打完,我们提交后可以惊现:

居然 MLE 了,此题的空间限制是 32MB。因此,我们需要一定程度上的优化我们的空间(当然也有些大佬一开始写的时候空间就比较小)。
- 如果是喜欢 define 来开 long long 的,要去掉。
- 如果是 dfs 统计环上节点数的,需要用循环。
- 可以把环上的 DP 滚动。
总结一下,这道题考验了一个基环树上的计算,以及一点点成分的 DP。
Code。

浙公网安备 33010602011771号