2025 Mar

Question 1. [省选联考 2025] 追忆

给定一张 \(n\) 个点 \(m\) 条边的 DAG,保证 \([1,2,\cdots, n]\) 为其的一个拓扑序,以及两个长度为 \(n\) 的全排列 \(A,B\),执行如下操作共 \(q\) 次:

  • 1 x y,表示交换 \(A_x,A_y\)
  • 2 x y,表示交换 \(B_x,B_y\)
  • 3 x l r,表示询问 \(x\) 的所有可达点 \(y\) 中,满足 \(A_y\in [l,r]\)\(B_y\) 的最大值。

多测。

\(T\leq 3, n,q\leq 10^5, m\leq 2\times 10^5\),时限 \(\text{8s}\)


首先,DAG 上可达点对就不是什么好做的东西,直接启发我们采用 bitset 及平方优化。

\(\mathcal{O}(\dfrac{nm}{\omega})\) 的复杂度内,求解 DAG 上的可达点对,接下来按照值域分块,假设块长为 \(B\),维护 \(A,B\) 在每一个块中的位置集合的 bitset

此时 \(1,2\) 操作可以 \(\mathcal{O}(1)\) 解决,重点是解决询问。

\(U\) 初始化为 \(x\) 的可达点集合,接下来计算 \(A_y\in [l,r]\)\(y\)bitset,记为 \(V_A\),将 \(A\) 中值域在 \([l,r]\) 内散块暴力改,整块直接按位或。

随后,按照从大到小的顺序,判断 \(B\) 的每一块是否有存在的位置,具体的,设当前 \(B\) 的值域块的位置集合的 bitset\(V_B\),求 \(U\cap V_A\cap V_B\) 是否非空即可,确定了大块之后再暴力确定答案是多少。

在上面的步骤中,单次询问的时间复杂度为 \(\mathcal{O}(\dfrac{n^2}{B\omega} + B)\),平衡块长取 \(B = \dfrac{n}{\sqrt{\omega}}\)

最终时间复杂度为 \(\mathcal{O}(\dfrac{nq}{\sqrt{\omega}})\),其中 \(\omega = 64\)

Question 2. [CEOI 2019] Amusement Park

给定一张有向图 \(G = (V,E)\),共计 \(n\) 个点 \(m\) 条边,没有自环与重边(方向相反的也没有)。

设一个边集的子集 \(F\subseteq E\),翻转边集 \(F\) 内的边的方向,若操作过后 \(G\) 变为 DAG 则权值为 \(|F|\),否则权值为 \(0\)

求权值的总和,答案对 \(P = 998244353\) 取余。

\(n\leq 18\)


首先,一张 DAG 反向后得到一张 DAG,一张非 DAG 反向后一定不是 DAG,设给这些边重定向成 DAG 的方案数是 \(C\),则答案为 \(C\times \dfrac{m}{2}\),根据前结论构造对应易得。

\(f_S\) 表示 \(S\) 内的点定向成 DAG 的方案数,那么怎么构建转移?在 DAG 上我们经常会考虑拓扑排序,在本 DP 中我们依旧考虑拓扑排序的思想——转移零入度点。

假设枚举的零入度点集 \(T\),那么有 \(T\) 向所有 \(S\setminus T\) 连边,且 \(S\setminus T\) 为 DAG,同时 \(T\) 是一个独立集(否则 \(T\) 之间一定存在边,那么怎么可能全部都是零入度点?),那么有 \(f_S = \underset{T\subset S}{\sum} w(T)f_{S-T}\),其中 \(w(T)\) 仅当 \(T\) 为独立集时取 \(1\)

但是这样会算重,具体的,\(T\) 作为最终的零入度点集,其所有子集都会被当作零入度点集计算,为了得到正确答案,我们采用容斥:在 \(|T|\) 为奇数时带 \(+1\) 的贡献,偶数时带 \(-1\) 的贡献,可以根据 Venn 图感性理解其正确性。

取最终 \(f_U\) 为方案数,根据结论乘上对应系数得到最终答案,其中 \(U\) 为点集的全集。

Question 3. [清华集训 2014] 主旋律

给定一张有向图 \(G = (V,E)\),无重边无自环,共计 \(n\) 个点 \(m\) 条边,求有多少个边的子集 \(F\subseteq E\) 满足 \(G' = (V,F)\) 是强连通的。

答案对 \(P = 10^9 + 7\) 取余。

\(n\leq 15\)


\(\text{trans}(A,B)\) 表示起点在 \(A\) 中,终点在 \(B\) 中的边的数量,以下使用这个函数时,(应该是)保证了 \(A,B\) 不交。

\(f_S\) 表示让点集 \(S\) 成为强连通图的方案数,考虑如何转移 \(f\)

根据强连通图的性质,其缩完点后只能得到一个点,枚举其的一个子集 \(T\),使得 \(T\) 构成了一个强连通分量,且在缩点之后的图上 \(T\) 的入度为 \(0\),不对 \(S\setminus T\) 有任何限制。

这样子会算重,借用前一个问题的容斥方法,我们将 \(T\) 划分成若干个强连通分量,若有奇数个则贡献为 \(+1\),反之为 \(-1\),记权值总和为 \(g_T\)

那么有 \(f_S = h_S - \underset{T\subseteq S}{\sum} 2^{\text{trans}(T,S\setminus T)} g_T h_{S\setminus T}\),其中 \(h_S\) 表示点集 \(S\) 能够导出的图的总数,设两端都在 \(S\) 中的边的数量为 \(x\),则 \(h_S = 2^x\)

考虑如何计算 \(g_S\),那么我们钦定其中的一个强连通分量 \(T\),使得 \(T\) 包含 \(S\) 中编号最小的点,这样子不会算重,则有 \(g_S = f_S + \underset{T\subset S}{\sum} (-1)f_Tg_{S\setminus T}\),其中这个 \(-1\) 表示多了一个强连通分量带来的变化,而 \(f_S\) 表示只有一个强连通分量。

注意到当 \(T = S\) 的时候 \(f,g\) 之间的互相转移看起来很奇怪,要先不管 \(f_S\) 计算 \(g_S\),然后计算 \(f_S\),最后再把 \(f_S\) 加到 \(g_S\) 当中。

为了计算 \(\text{trans}(A,B)\),预处理出每一个点的出边,然后枚举 \(A\) 中点,交 \(B\) 集合求 \(\text{popcount}(A\cap B)\) 后求和即可,时间复杂度为 \(\mathcal{O}(3^n n)\)

posted @ 2025-03-09 11:31  ydzr00000  阅读(50)  评论(0)    收藏  举报