【题解】[HNOI2015] 落忆枫音

题目传送门

感觉这题挺有意思的,遂写。

题目大意

给出一个有向无环图,再给定两个点 st,表示在点 st 间加上一条边。求这个图有多少种生成树。

题目分析

首先考虑不加边之前的情况,假设给定下面这个图:
image

根据树的定义,除根节点外的节点有且只有一个父亲节点,也就是说对于每一个节点,我们要指定一个唯一的父节点。比如上图的点 5,它在生成树上的父节点可以是 2 或者 6。又因为每个节点取父节点的情况互不干扰且是个无环图,所以用乘法原理可得生成树的方案有 i=2nin[i]in[i] 表示点 i 的入度,也就是有 in[i] 个父节点可能。

再考虑加上一条边后可能有环的情况。将上图添加一个由 62 的有向边。

image

此时,点 246 形成一个环。我们发现,即使现在点 in[2]=2,但它的合法方案只有 1,因为它的父节点不能为点 6,否则会形成环,不符合树的定义。

所以最后的方案数就等于所有方案数减去成环的方案数,而要使一个可以成环的点集成环,它有且只有一种方案,即每个节点的父节点都是上一个环上的点。如上图,若 6 的父节点是 44 的父节点是 2,但 2 的父节点是 1 的话,这时候不会形成一个环。

令集合 S 包含所有在环内的点,得出最后的结论:ans=i=2nin[i]iS,i1in[i]

我们令 dp[i] 表示从 ti 的含环数量,用拓扑排序维护转移。初始值 dp[t]=i=2nin[i],状态转移 dp[v]=dp[u]in[v]u 可达 v)。可以这样理解这个状态转移,由于多了一条 (s,t) 的边,所以所有从 ts 的路径上的点必然处于一个这条路径加上 (s,t) 所形成的环上,每次转移一次就相当于除上一个在环上的 in[i] 值,最后的 dp[s] 就是所有有环的方案数。

最后注意由于 st 多加了一条边,所以 in[t] 要加一。但拓扑排序时 in[t] 要减回来,否则不一定能遍历到它在环上。

总结

遇到在一个较简单的基础上增添一些性质的题,可以从简单的基础上出发,最后再减去不合法方案。

posted @   Cloote  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示