cfgym100026Acodecircles

Link

题意:

给定一个仙人掌,问有多少种划分点集的方案,使得每个点集内的点两两没有边。

做法

当时好像想了一会题意是不是仙人掌。后来想起来每条边在至多一个环就是仙人掌的定义。

首先考虑没有边的时候,等价于贝尔数,(不过当时没发现,用斯特林数求的)。贝尔数递推公式:枚举最后一个集合的元素:\(B_n=\sum \binom{n}{k}B_k\)

如果有边,遇到这种有限制的,考虑容斥每条边,变成必须在同一个联通块。

仙人掌可以考虑建出圆方树。树上 \(dp\),记录一下联通块个数。

树上 \(dp\) 的合并,只需要考虑合并一条边

要么是圆点->方点。要么是方点->圆点。

这里我第一遍没编清楚。

根节点是圆点的时候:我是同时枚举了首尾两条边,还需要额外记录首尾是否联通。

根节点是方点的时候:我让合并的第一个圆点不考虑连边。

这样写起来就不太优美。实际上可以把第一条边归到方点的讨论中。

这里还有个方点 \(siz=2\) ,即一条边的情况需要特判。

我在第一遍写的时候,试图直接 \(for\) 枚举钦定了多少条边。但是忘了乘组合数。最后还不如手动展开写。

还要注意不联通:图论必须要注意的:连通性,重边自环

复杂度是 \(O(n^2)\) 的,但是为了好写,我写的 \(O(n^3)\)

最后写了 \(20min\),调了 \(20min\)

后面又因为不知道还要 \(freopen\) 再调了 \(30min\)

总结

关键在于编一些分讨和细节的时候没有考虑全面。而且在想一些简单写法的时候,容易导致这种写法实现的功能和预期的不一样。

所以:想到做法之后,不仅要验证做法的正确性。

还要把细节(尤其是 \(dp\) 含义和转移)完全编明白。以及想到一个好写的写法之后,思考一下这个写法是否真的是对的。

关于\(bell\) 数和仙人掌的映射还没有建立到位。

\(bell\) 数:可区分的点,划分成若干集合

仙人掌:每条,在最多一个环。

图论必须要注意的:连通性,重边自环

仙人掌上 \(dp\) 转移:可以把一条边拆到一个点上。

调试:有好调的小样例,先输出调试(看不懂就输出)。

然后看题干,看漏写,看简单写法是否是等价实现。

接着根据思路的是否容易假:考虑对拍/静态调试/思考做法性质。

但是要注意:选择一个调试方法之前,优先考虑利用一些简单的手段/分析定位到错误的地方

这种树上 \(dfs\) 找环/仙人掌的题目,一定要记得在最开头判掉返祖边。

如果没有重边,可以直接 \(==fa\)。否则,\(vector\)\(pair\), 比较编号。

写的比较好的一个仙人掌模板:

模板

这个是狭义的仙人掌。判掉父亲边之后,如果 \(low[v]==dfn[u]\),就是环。否则就是一条边。

注意,不要判 \(stk[top]==v\),因为重边会需要建方点

posted @ 2026-05-22 23:29  Str_ywr  阅读(7)  评论(0)    收藏  举报