【题解】[HNOI2015] 落忆枫音

题目传送门

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

题目大意

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

题目分析

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

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

再考虑加上一条边后可能有环的情况。将上图添加一个由 \(6\)\(2\) 的有向边。

image

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

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

令集合 \(S\) 包含所有在环内的点,得出最后的结论:\(ans=\prod\limits_{i=2}^n in[i]-\prod\limits_{i\notin S,i\neq1}in[i]\)

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

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

总结

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

posted @ 2023-07-28 08:56  Cloote  阅读(23)  评论(0编辑  收藏  举报