题目链接
前言
做法
先看一眼数据范围,$n \le20$,那应该是个状压dp了。
为了方便说明,以直接覆盖来称那些我选的点,间接覆盖来称那些由于和直接覆盖的点相连,而不能选的点,被覆盖的点就是这两个点集的并。
首先先想到的自然是以$f[i],g[i]$分别表示目前被覆盖的点的状态为i时的最大独立集的大小和方案数。
先预处理选每个点会导致哪些点被间接覆盖,显然是与我直接相连的点,而我自己是直接覆盖。
考虑转移,枚举一个未被覆盖的点,更新一下f和g。
最后除以阶乘。
但是这样会有问题,以样例来说,3 1 2 与 3 2 1被当成了同一种状态,因为你并没有枚举间接覆盖点2在什么时候选。
所以我们用$f[i][j]$,$g[i][j]$来表示所有被覆盖的点集为i,被间接覆盖的点的点集为j。
但是这样复杂度显然爆了。
事实上所有被间接覆盖的点本质上都是一样的,所以我们并不需要知道是哪些,而只要知道有几个就行了。
如果一个点原先是被间接覆盖,我选他,相当于只把他这个点变成直接覆盖,而不把与他相连的点视为间接覆盖,因为事实上我并没有把它加入独立集,只不过相当于是在选择序列的最后把它加入。
用$f[i][j]$表示已经选了i个点,被覆盖的点集为j的最大独立集大小,$g[i][j]$表示方案数。
对于(i,j)统计出j中有多少个点已经被覆盖了,减去i就是被间接覆盖的点的个数了。
转移就分为取未被覆盖点还是间接覆盖点就行了。
代码
1 |
|