图上状压 DP
容易发现每年都在考这玩意。每年都不会。
关于代表元:
一般用 \(\min(s)\) 表示。通常在多个集合 \(s_1,s_2,\dots,s_m\) 合并的时候用已经维护出来的除开 \(\min(S)\) 外的集合并合并上包含 \(\min(S)\) 的集合来保证不计算重复。例如:\(1,2,3\) 的合并,\(\min(S)\) 属于 \(3\)。那么就可以用:\(F(\{1,2\})\) 与 \(F(\{3\})\) 合并。需要保证包含 \(\min(S)\) 的集合具有不可拆分性,例如 \(\{1,3\}\) 就可以拆成 \(\{1\}\) 和 \(\{3\}\),则不能用 \(F(\{2\})\) 与 \(F(\{1,3\})\) 合并。
AT_abc213_g [ABC213G] Connectivity 2
显然删边可以变成保留边。
定义状态函数 \(f_s\) 表示保留边,使得 \(s\) 中的点联通的方案数。那么对于 \(k=k0\) 来说,答案应该就是 \(\sum f_{s}[1 \in s \land k \in s]\times g_{U /s}\)。其中 \(g_s\) 为在任意保留 \((u,v) [u \in s \land v \in s]\) 中的边的方案数。
\(g_s\) 是好求的。时间复杂度 \(O(2^n n^2)\)。
\(f_s\) 有:\(f_s=\sum\limits_{\min(s') \subseteq t \subseteq s'}^{} f_{t}\times f_{s/t} \times h(s,t)\)。其中 \(h(s,t)\) 为至少保留一条 \((u,v) [u \in s \land v\in t]\) 的方案数。
这里以 \(\operatorname{lowbit}(s)\) 作为 \(s\) 的代表元,有 \(\min(s)=\operatorname{lowbit}(s)\)。代表元的作用是为了不让相同集合被计算多次,需要满足同种局面代表元唯一。
\(h(s,t)=2^{e(s|t)-e(s)-e(t)}-1\)。时间复杂度 \(O(3^n)\)。
发现对于 \((1,2),(2,3),(1,3)\) 会算重。
原因是这个代表元并不能唯一表示局面。在 \(s=\{1,2,3\}\) 时,可以 \(\{1\},\{2,3\}\),也可以 \(\{1,2\},\{3\}\)。如何?考虑容斥。因为在钦定一个集合 \(t\) 联通时,就可以统一了。因为 \(s\) 在不联通的时候一定由:\(t_1,t_2,\dots ,t_m\) 合起来。那么枚举包含 \(\min(s)\) 的集合,其它的就可以通过 \(2^{e(s/t)}\) 求得。
转移方程:\(f_s=2^{e(s)}-\sum\limits_{\min(s)\subseteq t \subset s}^{} f_t\times 2^{e(s/t)}\)。时间复杂度 \(O(3^n)\)。
P11714 [清华集训 2014] 主旋律
求删边的方案数。使得删完后仍为强联通图。
强联通图说明缩点之后是一个点。那么就是 \(2^m\) 减去缩完后是 DAG 的方案数。点数 \(>1\)。
如果求保留边,使得其是 DAG 怎么做。考虑 DAG 是加 \(0\) 度点的过程。定义状态函数 \(f_s\) 表示 \(s\) 中的点形成 DAG 的方案数。那么就是给 \(s/t\) 加一坨 \(0\) 度点。算重。例如 \(a,b\) 为 \(0\) 度点,连 \(s\) 中的点。在 \(a\) 为 \(0\) 度点,连 \(s\cup \{b\}\) 中的点与 \(b\) 为 \(0\) 度点,连 \(s\cup \{a\}\) 中的点时均会被算到。但是前面那个不会算 \((a,b)\) 或者 \((b,a)\) 的方案。那给它配个容斥系数,\((-1)^{|t|-1}\) 就行了。那么 \(f_s=\sum\limits_{\emptyset \subseteq t \subseteq s}^{} f_{s/t} \times g(s/t ,t)\times (-1)^{|t|-1}\)。其中 \(g(s,t)\) 表示 \(t\) 中点向 \(s\) 中点任意连边的方案数。
求 \(g(s,t)\)。\(g(s,t)=g(s,t/\min(t))\times G(s,\min(t))\)。其中 \(G(s,i)\) 为 \(i\) 向 \(s\) 中点任意连边的方案数。那么枚举 \(s\),枚举 \(U/s\) 的子集 \(t\)。从小到大枚举,则 \(t /\min(t)\) 一定在 \(t\) 之前被算到。时间复杂度 \(O(3^n+2^nn^2)\)。
那缩完之后是 DAG 怎么做呢。把一个强联通分量看成一个点。那么定义 \(f_s\) 表示将 \(s\) 中的点缩点后形成 DAG 的方案数。维护 \(g_{s}\) 表示将 \(s\) 中的点缩成若干个不联通点的方案数。但是这个容斥并不好做。因为 \(s\) 中缩成奇数个点和偶数个点被重复计算的次数不同。观察之前的容斥系数 \((-1)^{|t|-1}\)。也就是说,当 \(|t|\) 是奇数时为正,偶数时为负。
这启示我们提前计算容斥系数。也就是 \(g_s= x_s -y_s\)。其中 \(x_s\) 为 \(s\) 缩点后剩下奇数个不联通点的方案数,\(y_s\) 为 \(s\) 缩点后剩下偶数个不联通点的方案数。对于转移,定义 \(dp_s\) 为将 \(s\) 中的点缩成一个点的方案数。那么 \(dp_s=2^{e(s)}-f_s\)。有 \(g_s=dp_s - \sum\limits_{\min(s) \subseteq t \subset s}^{}g_{s/t} \times dp_{t}\)。
则对于 \(f_s\) 的转移,就可以省略掉容斥系数了。有 \(f_s=\sum\limits_{\emptyset\subseteq t \subseteq s}^{}2^{e(s/t)} \times g_{t} \times h(s/t,t)\)。这里函数名重了,\(h(s,t)\) 仍然表示 \(t\) 中点任意连向 \(s\) 中点的方案数。时间复杂度 \(O(3^n +2^nn^2)\)。但是空间好像是 \(O(4^n)\) 的。哦,发现 \(s \cap t=\emptyset\),所以空间 \(O(3^n)\)。
空间怎么 \(O(3^n)\)。MLE 了。重新看一下 \(h(s,t)\),它的意思是 \(t\) 中点任意连向 \(s\) 中点的方案数。也就是说需要维护出 \(\sum\limits_{i=1}^{m}[u_i \in t \land v_i\in s]\)。发现每次 \(O(\operatorname{popcount}(t))\) 求就行了。时间复杂度 \(O(3^nn)\),但是可过。
AT_arc105_f [ARC105F] Lights Out on Connected Graph
求删边后是二分图的方案数。
如果确定左部节点的集合 \(S\),那么右部节点的集合为 \(U/S\)。方案数就是 \(h(S,U/S)\)。其中 \(h(s,t)\) 为 \(u \in s\land v\in t\) 的边任意保留的方案数。
但是这个会算重。因为二分图可以看做若干个联通的二分图拼起来的,且拼接方案数是 \(2^{cnt}\),即每个联通子图任意交换左右部节点不影响。
那么定义状态函数 \(f_s\) 表示 \(s\) 是一个联通二分图的方案数。则一定有:\(U=\bigcup\limits_{i=1}^{m}s_i\)。那么再维护 \(dp_s\) 表示 \(s\) 是二分图的方案数。则:\(dp_s=f_s+\sum\limits_{\min(s) \subseteq t \subset s}^{}dp_{s/t}\times f_{t}\)。
求 \(f_s\)。因为联通,所以 \(s = x \cup y\)。其中 \(x\) 是左部节点,\(y\) 是右部节点。但是维护任意连 \(y\) 与 \(x\) 之间的边,使得 \(s\) 联通的方案数不好做。那么尝试容斥。总的减去不是联通二分图的方案数。那么有:\(f_s=g_s-\sum\limits_{\min(s)\subseteq t \subset s}^{} f_{t}\times g_{s/t}\)。其中 \(g_s\) 为 \(s\) 是二分图的方案数。有 \(g_s=\sum\limits_{\emptyset\subseteq t \subseteq s}^{} h(t,s/t)\)。哦,这样算出来 \(f_s\) 其实多算了一倍,因为左右部节点不区分,则:\(dp_s=\frac{1}{2}f_s+\sum\limits_{\min(s) \subseteq t \subset s}^{}dp_{s/t}\times \frac{1}{2}f_{t}\)。
时间复杂度 \(O(3^n)\)。
哦,唐了。题目要求联通。那么答案就是 \(\frac{1}{2}f_{U}\)。
AT_abc306_h [ABC306Ex] Balance Scale
如果没有等于号,那么就是求删边的方案数。使得生成的图是 DAG。这个在主旋律的时候已经求解。有:\(f_s=\sum\limits_{\emptyset \subseteq t \subseteq s}^{} f_{s/t} \times h(s/t ,t)\times (-1)^{|t|-1}\)。时间复杂度 \(O(3^n)\),空间 \(O(3^n)\)。
如果有等于号。那么相当于是合并 \(u,v [a_u=a_v]\) 后是 DAG。预先合并。那么对于一个联通块内的点,边也是任意保留的。但是加入度数为 \(0\) 的点时,\(|t|\) 应当变成 \(t\) 中联通块的数量。则:\(f_s=\sum\limits_{\emptyset \subseteq t \subseteq s}^{} f_{s/t} \times h(s/t ,t)\times m(t)\times (-1)^{|b(t)|-1}\)。其中 \(m(s)\) 为 \(s\) 中任意保留等于号的边的方案数,\(b(s)\) 为 \(s\) 中联通块的数量。时间复杂度 \(O(3^n)\),空间 \(O(3^n)\)。
哦,边是自己给的。读错题了。维护 \(g_t\) 表示 \(t\) 中的点任意合并后乘上容斥系数的和。那么 \(g_{s}=dp_s -\sum\limits_{\min(s) \subseteq t \subset s}^{} g_{s/t}\times dp_{t}\)。其中 \(dp_s\) 为任意保留 \(s\) 中的边,使得 \(s\) 为联通块的方案数。继续容斥,那么 \(dp_s=2^{e(s)}-\sum\limits_{\min(s) \subseteq t \subset s}^{} dp_t \times 2^{e(s/t)}\)。则对于 \(f_s\),有:\(f_s=\sum\limits_{\emptyset \subseteq t \subseteq s}^{} f_{s/t} \times h(s/t ,t)\times g_t\)。时间复杂度 \(O(3^n)\),空间复杂度 \(O(3^n)\)。
可恶。又读错题了。不是删边,是给边定向……那么 \(h(s,t)=1\),且 \(t\) 内部的边必须是等于号。也就是说 \(b(t)\) 唯一。时间复杂度 \(O(3^n+2^nn^2)\)。空间 \(O(2^n)\)。弱。
CF1556F Sports Betting
转到图上理解。就是给边 \((u,v)\) 定向后得到有向图 \(G\)。求图 \(G\) 中能够到达 \(1\sim n\) 所有点的点数的期望。
期望转方案数。那么这个图 \(G\) 存在满足题意的点的条件是?显然是在缩点后只存在一个入读为 \(0\) 的点的情况下这个入读为 \(0\) 的点的大小,也就是该强联通分量的大小。
竞赛图缩点后是条链。那么入读为 \(0\) 的点一定只有 \(1\) 个。那么枚举点集 \(s\) 为该入读为 \(0\) 的点,且 \(s\) 构成的子图是强联通分量。则方案数就是 \(f_{s} \times 2^{\frac{n(n-1)-\operatorname{popc}(s)(\operatorname{popc}(s)-1)}{2}}\)。那么现在问题变成:求集合 \(s\) 构成的子图是强联通分量的方案数。显然直接主旋律可做。
但是这题 \(n \le 14\),且保证图是完全图,且时限 \(4s\)。哦,有个很简单的东西。既然都有上面那个方案数了,如何不能直接做。定义状态函数 \(f_s\) 表示 \(s\) 强联通的概率。那么考虑容斥:\(f_s=1-\sum\limits_{\emptyset \subseteq t \subset s}^{}f_t \times h(t,s/t)\times g_{s/t}\)。其中 \(h(s,t)\) 表示所有满足 \(u \in s \land v\in t\) 的边都有 \(u \to v\) 的概率。\(g_{s}\) 表示 \(u\in s\land v\in s\) 的边任意定向的方案数。显然 \(g_s=1\)。则:\(f_s=1-\sum\limits_{\emptyset \subseteq t \subset s}^{}f_t \times h(t,s/t)\)。
最后答案就是 \(\sum f_s \times h(s,U/s) \times \operatorname{popc}(s)\)。时间复杂度 \(O(3^n)\)。空间依旧小炸。但是时间换空间无妨。变成 \(O(3^nn)\)。
CF1155F Delivery Oligopoly
求最少保留多少条边,使得图是一个点双联通分量。
因为是最优性问题,所以重复计算没影响。那就上暴力吧。定义状态函数 \(f_{s}\) 表示 \(s\) 是一个点双联通分量时最少保留的边数。点双是若干个环的并。也就是说,\(s\) 拓展到 \(s’\) 的过程是不断加链,链的两端与当前集合中的某两(一)个点相连的过程。那么分步合并,每次加一条链。
对于 \(f_s\),有:\(f_s =\min(\operatorname{popc}(s)[g_s=1],\min\limits_{\emptyset \subset t \subset s}^{}\min\limits_{x\in t}^{}\min\limits_{y\in t}^{}f_{t}+(\operatorname{popc}(s/t)+1)[h_{(s/t),x,y}=1])\)。其中 \(h_{s,x,y}\) 为是否存在一条链使得链经过了 \(s\) 中所有点,且链头与 \(x\) 有边,链尾与 \(y\) 有边。 \(g_{s}\) 为是否存在一个经过了 \(s\) 中所有点的环。(在 \(\operatorname{popc}(s)=1\) 时 \(h_{s,*,*}\) 与 \(g_{s}\) 均为 \(0\))。
\(h_{s,x,y}\) 可以 \(O(2^nn^3)\) 暴力维护。且 \(g_s\) 可以通过 \(h_{s,x,y}\) 推出。那么时间复杂度就是 \(O(2^nn^3+2^nn^2+3^nn^2)\)。
发现有点炸。一个点是可以经过多次的,因为保证任意两个点至少存在两条不交路径并不能说明存在哈密顿路径。且复杂度好像有点炸。前面那个问题简单处理。
沃日,怎么就是 \(O(3^nn^2)\) 的。求不到意义。
P6846 [CEOI 2019] Amusement Park
求改变边的代价和,代价为改变的边数。使得改变后图是 DAG。
DAG 是加入度为 \(0\) 的点的过程。定义状态函数 \(f_{s}\) 表示点集 \(s\) 的子图是 DAG 的代价和,\(g_s\) 为方案数。那么有:\(f_{s}=\sum\limits_{\emptyset \subset t \subset s}^{}(f_{s/t}+g_{s/t}\times h(s/t,t) )\times (-1)^{|t|-1} [e(t)=0]\)。因为不能删边,所以需要保证加入的度数为 \(0\) 的点之间没有边。\(h(s,t)\) 表示所有 \(u \in s,v\in t\) 的边都有 \(v \to u\) 的代价和。则 \(g_{s}=\sum\limits_{\emptyset \subset t \subseteq s}^{}g_{s/t}\times (-1)^{|t|-1} [e(t)=0]\)。容斥系数比较显然,\(x\) 个度数为 \(0\) 的点被算了 \(x\) 的子集数量次。时间复杂度 \(O(3^n)\)。MLE 了。需要优化 \(h(s,t)\)。好像主旋律也可以这样。
发现 \(h(s,t)\) 与 \(h(s / \{x\},t \cup \{x\})\) 的关系是:\(h(s,t)=h(s / \{x\},t \cup \{x\})+\sum [v=x \land u \in (t\cup \{x\})]-\sum[u=x \land v\in (s/\{x\})]\)。时间复杂度 \(O(3^n)\),空间 \(O(2^nn)\)。
怎么正解不是 \(O(3^n)\),需要卡常。
P5492 [PKUWC2018] 随机算法
先看最大独立集怎么求。
枚举状态 \(s\),\(O(m)\) 判断可行性做到 \(O(2^nm)\)。通过上一个状态加点,\(O(n)\) 判断做到 \(O(2^nn)\)。
那么我们只需要求最后 \(S\) 属于答案集合的排列 \(p\) 的数量。
更简单地,只需要关系最后 \(S\) 的大小是否等于最大独立集的大小。
如果 \(x\) 能加入 \(S\),说明所有和 \(x\) 有连边的点都没被加入 \(S\)。那么 \(\forall(u,v)\in E \land u=x ,tim_v >tim_u\)。那么逐一确定加入 \(S\) 中的点的值后,就会有若干个形如 \(tim_v > tim_u\) 的限制。显然,由于 \(S\) 是最大独立集,所以只用考虑这些限制可以满足时 \(p\) 的数量,而不在意会不会有新的点被加进来。
发现 \(p_1\) 一定是 \(S\) 中的点,因为它一定会加到 \(S\) 中。发现相邻两个 \(S\) 中的点之间的点一定会和之前的一个 \(S\) 中的点有连边,否则会加入 \(S\) 中。
定义状态函数 \(f_{j,s}\) 表示现在独立集为 \(s\),且有 \(j\) 个与 \(s\) 中点有连边的点还没确定位置的方案数。可以做到 \(O(n^22^n)\)。很没前途。
考虑到这题只需要求概率,而不在意方案数。那么只要确定了 \(S\) 中有哪些点,它们的顺序是什么,就可以直接计算答案了。因为对于一个不在 \(S\) 中的点 \(v\),只要找到第一个加入 \(S\) 中且与它相连的点 \(u\),让 \(tim_v >tim_u\) 就行了。这样不在 \(S\) 中的点就对概率不产生影响(但对方案数显然会产生影响)。
那么问题变成:每次选择一个未被标记的点,并把和它有连边且未被标记的点标记(包括自己),然后将这个点加入 \(S\) 中。求最后 \(S\) 的大小最大的概率。
定义状态函数 \(f_{s}\) 表示当前被标记的点的集合为 \(s\) 的概率。首先选择 \(x\) 的概率为 \(\frac{1}{n-|bel_s|}\)。那么:\(f_{s|x}=f_{s}\times \frac{1}{n-|bel_s|}\)。时间复杂度 \(O(n2^n)\)。
AT_arc078_d [ARC078F] Mole and Abandoned Mine
求删边的最小代价,使得删完后 \(1\) 到 \(n\) 不经过重复点的路径唯一。
\(1\) 到 \(n\) 的路径应该是 \(P_1,P_2,\dots,P_k\),且 \(P_1=1,P_k=n\)。那么剩下 \(n-k\) 个点和一些边一定是通过连接 \(1\) 和 \(n\) 得到。且不可能同时和 \(1,n\) 联通(删去 \(P_2\dots P_{k-1}\) 后)。维护 \(f_{s,x}\) 表示一条点集为 \(s\) 的链,开头为 \(1\),结尾为 \(x\) 的最小代价。有转移方程:\(f_{s\cup \{u\},u}=\min\{spd_u+f_{s,x}-w_{x,u}-\sum\limits_{v\in s}^{}w_{u,v}\}\)。特殊转移 \(u=1\),对于 \(u=1\),有:\(f_{\{1\},1}=spd_1\)。
注意到其实这个链上面可以挂一些其它的链,就像树的直径那样。维护 \(dp_s\) 为在一条 \(1\sim n\) 的链上挂一些链,集合为 \(s\) 的最小代价。那么 \(dp_{s}=\min(f_{s,n},dp_{s/x}-\max\limits_{y\in (s/x)}^{}w_{x,y}+spd_x-\sum\limits_{v\in (s/x)}^{}w_{x,v})\)。
然后考虑把剩下的点拼起来。维护 \(g_{s}\) 表示将 \(s\) 中的点分成两半,一半和 \(1\) 连,一半和 \(n\) 连的最小代价。那么:\(g_{s}=\min\limits_{\{1\} \subseteq t \subseteq s/\{n\}}^{}h(t/\{1\},s /t/\{n\})-\sum\limits_{u\in t\land v=n}^{}w_{u,v}-\sum\limits_{u\in (s/t)\land v=1}^{}w_{u,v}\)。其中 \(h(s,t)\) 为删掉所有 \(u\in s \land v\in t\) 的代价。
那么最后答案就是 \(\min dp_{s}+g_{t}+h(t/\{1,n\},U/s/t)[s\cap t =\{1,n\}]\)。那么时间复杂度就是 \(O(3^n+2^nn^2)\)。
发现其实 \(dp_{s}\) 不能只维护挂链,因为挂的链内部也可以有连边(可以看做是挂了个联通块),如果单纯维护链会错 \(2\) 个点。维护简单,和 \(dp_s\) 的转移方程差不多。复杂度仍为 \(O(3^n+2^nn^2)\)。

浙公网安备 33010602011771号