CF1804E:Routing 题解

题意:(n<=20) 给出n个点的无向连通稠密图,请你给每个点指定一条边,使得从任意点出发沿着指定的边走,并不断标记自己和所有邻居点,都可以标记完整张图。

Solution:

每个点只能选取一条边,因此n个点选完边后会构成一个基环树。从所有点出发最终都会沿着那个环走,这就要求基环树中环上的子树深度只能是1,否则环上的点就无法标记更子树内更远处的点。

这题是一道状压小练习,细节还蛮多,调起来生动活泼且有趣。

直接DFS枚举环复杂度很难保证,有个同学好像直接写的DFS爆搜结果fst了。

从题解中学到一个保证 \(n2^n\) 的做法:

我们目的主要是找到这个环,只要能找到一条可以首尾相接的链即可。设 \(f[i][S]\) 表示以 i 作为初始点,链上有集合 S 中的点时,可能成为链的末尾点的集合。顾名思义,\(f[i][S]\) 是 S 的一个子集。

发现不太优美,这个做法是 \(n^22^n\),因为我们同一个环用了很多起始点来表示,我们钦定每个环只能以编号最小的点作为起始点。dp 状态改为 \(f[S]\) 表示以 S 中最小的点作为起始点,链上有集合 S 中的点时,可能成为链的末尾点的集合。

转移时,对于每个状态,我们枚举下一个往链上添加的点,更新之后的状态,并检查当前状态是否合法(当前链是否能拼接成环,以及基环树是否能标记整个图),合法就跳出来输出答案即可。

题目要求输出方案,比较头痛的一件事,不过也简单。从合法的方案 S 开始,每次取 \(f[S]\) 中的任意一点作为末尾点,并从 S 中去除这个点,这样就能把整个环给找出来。

为了节省时间,我们还需要把每个点的相邻点压缩成一个集合,以位运算代替枚举。细节比较多,可以锻炼对状压dp的驾驭能力。

my submission

posted @ 2024-02-05 20:52  maple276  阅读(7)  评论(0编辑  收藏  举报