Processing math: 2%

有向图子图 DAG 数量

考虑 DP,朴素的想法是令 f_S 表示 S 这个导出子图将边定向集合构成 \tt DAG 的方案数。

转移可以考虑剥去所有入度为 0 的点,那么我们就需要得到仅存在 T 这个子集为 S 中入度为 0 的点的方法。

直接做是困难的,考虑容斥。

强制钦定 T 这个子集为 S 中入度为 0 的点,其他的点不管,T \rightarrow S - T 的边显然可以连或不连,而 S - T \rightarrow T 中间的边必须强制不连,这样可以得到转移(注意是强制钦定的转移):

f'_S = \sum\limits_{T \subseteq S, T \ne \varnothing} 2 ^ {ways(T, S - T)} \times f_{S - T}

q_T = 2 ^ {ways(T, S - T)} \times f_{S - T},令 S 中恰好仅有 T 做为入度为 0 的点的方案为 p_T,那么有:

q_T = \sum\limits_{T \subseteq S} p_S

根据二项式反演的集合形式,有:

p_S = \sum\limits_{S \subseteq T} (-1) ^ {|S| - |T|} q_T

在本题中,我们需要求:

\begin{aligned} & \sum\limits_{T \subseteq S, T \ne \varnothing} p_T \\ &= \sum\limits_{T \subseteq S, T \ne \varnothing} \sum\limits_{T \subseteq R, R \subseteq S} (-1) ^ {|T| - |R|} q_R \\ &= \sum\limits_{T \subseteq S} (-1) ^ {|T| - 1} q_T \end{aligned}

因此有 f 的转移:

f_S = \sum\limits_{T \subseteq S, T \ne \varnothing} (-1) ^ {|T| - 1} \times 2 ^ {ways(T, S - T)} \times f_{S - T}

此时只要处理出 ways(T, S - T) 即可做到 \mathcal{O}(3 ^ n)

对于每个 S,我们考虑单独计算 ways(T, S - T)(T \subseteq S),将其简写为 w_T

w_T 进行 \tt DP,显然每次只需取出一个在 T 中的点进行转移即可,可以使用 \mathtt{lowbit}, \mathcal{O}(1) 取出。

转移只需预处理出 w1_{i, S}, w2_{i, S} 分别表示 i \rightarrow S 中的边数和 S \rightarrow i 中的边数即可,这部分直接暴力。

于是本题可以做到时间复杂度 \mathcal{O}(3 ^ n),空间复杂度 \mathcal{O}(n \times 2 ^ n)

posted @   Achtoria  阅读(628)  评论(6编辑  收藏  举报
编辑推荐:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示