最搞笑的一集,复杂度瓶颈在预处理。
首先我们知道如果强连通变成 DAG 咋做:
这个 \(-1\) 是容斥系数,相当于将 DAG 每次分层,考虑这个容斥让问题变成了什么,是可以不用记录最后一层点的!因为如果不记录这个的话你不知道 \(S - T\) 里是否还有入度为 \(0\) 的点,使用子集反演可以变成这个形式,也是一个特别经典的问题,可以当一个 trick 记录下来。
为什么我们要解决这个问题,是因为将非强连通图缩点后必定是一个 DAG,我们只需要看哪些点缩在一个 SCC 里就可以了。
设 \(f_S\) 为缩成一个 SCC 的方案数,\(g_S\) 为缩成若干个入度为 \(0\) SCC 的方案数,相当于换了个壳,状态转移式如下:
现在容斥的意义就变成了 \(S - T\) 这个集合里的数可以随便连边,但是 \(x\) 我们是不知道的,因为它是 \(T\) 中缩成的 SCC 数量 \(+ 1\),考虑解决 \(-1\) 的常用 trick,将个数带入 \(g_T\) 里计算,相当于 \(SCC\) 个数是奇数的权重为 \(1\),否则是 \(-1\),这样只与奇偶性有关。考虑到这一点,接下来考虑 \(g_S\) 的转移:
此时 \(-\) 恰好将后面那依托东西的正负号取反,SCC 个数的奇偶性也变了。但是会算重,使用经典手法固定 \(lowbit\),就可以不重不漏了。
但是你发现 \(f_S\) 与 \(g_S\) 的转移在 \(g_S\) 的时候会变成环,你仔细理解一下过程,发现当 \(f_S\) 转移是 \(g_S\) 包含 \(f_S\) 并不合法,于是将环手动拆开即可。