A Simple Task 题解
这道题比较简单,简述一下思路。
考虑状压 \(DP\)。
设 \(dp_{i,j}\) 表示走到第 \(i\) 个点,之前走过的点的状态为 \(j\) 的环的数量。这里有一个细节,就是我们都钦定每个走过的第一点是整个状态中编号最小的点,这样不会重复计算。
考虑如何进行转移。如果当前点的编号比走过的最小编号还小就直接跳过这种情况。如果当前点没有走过,就走;如果走过且形成了环的话,就把答案加上。
for(int i = 0;i < (1 << n);i++)
for(int j = 0;j < n;j++)
{
for(int k = head[j]; ~ k;k = e[k].nxt)
{
int now = e[k].v;
if((1 << now) < (i & -i)) continue;
if((1 << now) & i)
{
if((i & -i) == 1 << now) ans += dp[i][j];
}
else dp[(1 << now) | i][now] += dp[i][j];
}
}
因为是无向边,所以每个环会被计算两次,还会计算二元环。最后将这些减掉就可以了。
本文作者:Creeper_l
本文链接:https://www.cnblogs.com/Creeperl/p/17913373.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步