记录一种DAG计数方法与一个配套技巧
记录一种DAG计数方法与一个配套技巧
定义 \(f_S\) 表示集合 \(S\) 中的点构成的合法 DAG 子图的方案数。假设找到 DAG 中一个入度为 \(0\) 的节点 \(x\),那么很明显 \(f_S=\sum_{x}f_{S\setminus \{x\}}\),这明显要算重因为 \(S\setminus \{x\}\) 中也有入度为 \(0\) 的点。
于是有一个容斥的想法,设 DAG 中一个入度为 \(0\) 的点集至少是 \(T\),根据容斥的思想,其应该贡献 \((-1)^{|T|+1}\) 的权值
于是有表达式 \(f_S=\sum\limits_{T\subseteq S,T\ne \emptyset}f_{S\setminus T}(-1)^{|T|+1}\) 。
技巧:一个判断点集 \(T\) 是否能到点集 \(S\) 的方法:记录所有可以到点集 \(S\) 的点的集合 \(from[S]\),直接看 \(T\cap from[S]=\emptyset\) 即可。
注意:c++ 中 & 运算的优先级低于 == 运算。
P6846 [CEOI 2019] Amusement Park
CF1193A Amusement Park 与这道题是双倍经验
用一种对称的观点看,我们发现若存在一种翻转 \(x\) 条边的方案,那么一定存在另一种翻转 \(m-x\) 条边的方案,那么问题变成了:给定一个无向图,你可以给边定向,求无向图个数,最后乘上 \(\frac m2\)。
于是设 \(f_S\) 表示点集 \(S\) 构成的子图的合法 DAG 数量,根据上面的方法,有 \(f_S=\sum_{T\subset S,T\ne \emptyset}(-1)^{|T|+1}f_{S\setminus T}\times c(T)\) 其中 \(c(T)\) 表示 \(T\) 集合中是否两两无边。
AT_abc306_h [ABC306Ex] Balance Scale
如果不考虑 =,那么容易发现答案不合法当且仅当有同序的关系构成了一个环,于是这就是一个 DAG 计数,与上一道题是一模一样的。
容易发现添加了 = 后,相当于把几个点构成的子连通块合并在了一起,类比一下,发现可以把这样一个连通块当作一个“点”进行添加,即:

同理配容斥系数,设 \(cnt_T\) 表示一个点集 \(T\) 的子图联通块数,则:
\(f_S=\sum_{T\subseteq S,T\ne \emptyset}(-1)^{cnt_T+1}f_{S\setminus T}\)
\(\mathcal O(3^n)\) 已经可以解决这道题。
更优的复杂度:发现这是一个子集卷积,用子集卷积可以做到 \(\mathcal O(2^nn^2)\) 的复杂度。
TG178X 的模拟赛题“单独行动”
题目:给一个 \(n\) 个点,\(m\) 条边的无向图,每条边 \((u,v)\) 分别有 \(\frac 13\) 的概率变为 \(u\to v,v\to u\) 和消失,求最后为 DAG 的概率。
\(n\le 20\)
首先按照方法设出 dp 并写出转移式:
其中 \(E(S)\) 表示两端都在 \(S\) 中边数。这道题 \(\mathcal O(3^n)\) 过不了。
将式子变为:
这可以子集卷积,复杂度 \(\mathcal O(2^nn^2)\)。
P10221 [省选联考 2024] 重塑时光
不难发现 \(k=0\) 就是 DAG 拓扑排序数,用一个简单的状压 DP 即可解出。
当 \(k\ne 0\) 时,相当于将点集分成了小于等于 \(k\) 块(先不考虑空集),求块内是合法的 DAG 拓扑排序,块间不存在环的方案数。“不存在环”就是 DAG,块间变成了一个 DAG 计数,而块内我们已经解决了,这是一个正确的思路。
设 \(S\) 块内重排列满足条件的方案数为 \(h_S\),有:
其中 \(c(S,T)\) 表示 \(S\) 不能到 \(T\)。
设 \(g_{S,i}\) 表示把 \(S\) 中的点分成 \(i\) 块使得其中块间两两无边的方案数,有:
设 \(f_{S,i}\) 表示把 \(S\) 中的点分成 \(i\) 块使得构成 DAG 的方案数,有:
最终答案为 \(\frac{k!(k+1)!}{(n+k)!}\sum_{i}\frac {f_{U,i}}{(k+1-i)!}\)。
于是可以在 \(\mathcal O(n^23^n)\) 的时间复杂度下求解,然而还可以更快。
容易发现上面的转移式是一个卷积。设 \(F_S(x)=\sum\limits_{i}f_{S,i}x^i,G_S(x)=\sum\limits_{i}g_{S,i}(-1)^{i+1}x^i\),则上述转移式可以改写为:
带 \(n\) 个 \(x\) 进去求出值后,再用拉格朗日插值求出系数即可。
复杂度 \(\mathcal O(n3^n+n^22^n)\)。
P6295 有标号 DAG 计数
先咕
【清华集训2014】主旋律
这是求强连通的子图,我们知道强连通图缩点后就是一个点,而非强连通图缩点后就是DAG,于是可以通过 DAG 计数的方法计算出非强连通图的个数后,从而得到强连通图的个数。
设 \(f_S\) 表示点集 \(S\) 的强连通子图的方案数,可以套路的列出下列式子:
其中 \(E(S,T)=|\{(u,v)|u\in S,v\in T\}|\)。
\(g_T\) 是点集 \(T\) 的带容斥系数的分成若干强连通分量的方案数,这里的容斥系数本来应该是 \((-1)^{强连通分量数+1}\),但由于并不知道具体强连通分量数,只能如此处理。枚举其中一个元素所在的强连通块,有如下式子:
注意:
- 
根据定义 \(-f_Sg_{\emptyset}\to g_S\) 的更新应该放在 \(f_S\) 处理完毕之后。 
- 
\(g_{\emptyset}=-1\) 
代码:提交记录 #739694
HDU 4997 Biconnected
题意:给一张图,问有多少种加边的方法,使得图是边双。
GYM 102331C Counting Cactus
题意:给一张图(无重边自环),求有多少个边的子集使得没有任何一条边在两个环中。 (生成边仙人掌计数)
一个参考文章:一类图论相关的状压 DP 题的常见解法 - Mackerel_Pike - 博客园,里面说这种方法不仅可以运用在DAG计数,还可以运用在连通图、强连通、双连通图的计数与最优化上。其中计数问题需要容斥,最优化问题则不需要。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号