[ZJOI2018]树

鸽子更博了!

如今大学已尘埃落定,终于成功进入清华,不过不在计算机系。还是希望将OI作为一种爱好,也想找机会参加acm,因此还是会时不时复健一下。这一题是我记忆中攻克最艰难、解题后也最痛快的一题,因此印象深刻。当然我早已忘了具体的步骤,因此最近重做了一遍,也算是对自己的魔鬼训练吧。

与群论相关的前置知识: 设G是所有长度为n的置换构成的群,X是一些长度为n的序列构成的集合。如果将G作用于X,那么: 对于xX,称{yX|y=f(x),fG}x的轨道,记为Orbit(x),对于yOrbit(x),称yx的等价类。 对于xX,称{fG|x=f(x)}x的稳定化子,记为SG(x)。 对于fG,称{xX|x=f(x)}f的不动点,记为fix(f)

与题意类似,我们定义两个森林同构,当且仅当可以通过某种一一对应关系,使得一个森林的任意一棵树都和另一森林对应的树同构。

cntnn个点的无标号有根树个数,并令所有树从1cntn标号。

那么令Sn,i表示所有按照题目要求构造的带标号有根树中,与n个点的i号无标号有根树同构的那一部分构成的集合。

由于按照题意建立的n个点的树共有(n1)!种,因此

ans=1(n1)!ki=1cntn|Sn,i|k

那么重点关注后半部分,尝试利用动态规划的方法解题。那么令:

dpn=i=1cntn|Sn,i|k

考虑如何转移。回想判断无标号有根树同构的过程:先将根的所有子树按照一定规则排序,逐一比较即可。那么是否可以先枚举排序后在最后的子树,将其删去递归求解,再考虑这棵子树的贡献呢?

但是,如果枚举排在最后的子树,那么就隐含了条件:对于递归的树,其根的所有子树的优先级一定在该子树之前(或者就是该子树),而子树的数目众多,无法比较好的设计状态。

但这样的思考并不是毫无意义的。虽然枚举最后的子树不太现实,但也许可以退而求其次,对子树先进行一个“粗略的划分”,而非直接一个个分离。不难想到先根据子树大小从小到大初步排序,每次删去大小最大的那一批子树,对剩余的树进行递归求解,再考虑这些相同大小的子树的贡献。那么对递归求解的树的额外要求,就转变为了根的子树大小不能超过某个值,不仅状态大量减少,考虑起来也非常方便。

那么为了方便,我们记mxs(Sn,i)表示对于集合Sn,i中的树,他们根的子树的最大大小,类似记mns(Sn,i)表示最小的。根据上面的想法,可以设计辅助状态:

tmpn,p=i=1cntn[mxs(Sn,i)p]|Sn,i|k

则有dpn=tmpn,n1。再考虑状态的转移。那么就枚举大小为p的根的子树的数目,分配标号,再将前后部分独立考虑。前半部分可以递归到之前的状态,但后半部分无法递归,需要单独解决,表示成式子,就是:

tmpn,p=u=0n1p(n1up)ktmpnup,p1fp,u

因为1号点显然是根,所以实际分配的标号只有n1个。其中:

fp,u=i=1cntup+1[mns(Sup+1,i)=mxs(Sup+1,i)=p]|Sup+1,i|k

表示需要单独解决的那一部分。之所以大小为up+1,是因为我们给着u棵大小为p的树额外加了一个形式上的根,方便考虑问题。那么第一步先考虑标号的分配。

按照常规来讲,标号的分配应该是(upp,p,,p)种情况,但在此处,由于根的所有子树之间是没有顺序的(这也是之前进行“粗略的划分”遗留下来的问题),因此如果出现两棵相同的子树,它们的地位完全等价,也即即使赋予它们的标号互换,得到的也是同一种结果。但是(upp,p,,p)的分配方式显然将互换前后看作不一样的。

看来(upp,p,,p)并不能适用于所有情况,还需要进行进一步的分类讨论。那么我们假设其中某一个Sup+1,i,其根的子树可以分为m类本质不同的,且数目分别为a1,a2,a3,,am((t=1mat)=u),也不妨将a不降序排序。对于同一类的子树内部,任意两棵树都可以互换标号,因此分配给这一类的at组标号彼此是无序的,需要将分配标号方案数乘以1at!。因此对这一情况,分配的方法数应该为:

(upp,p,,p)(t=1m1at!)=(up)!(p!)u(t=1m1at!)

初步解决分配标号的问题后,我们再考虑下一步操作。此时只要将u棵子树内部的标号都看作是1,2,,p即可,此时可以去掉形式上的根,将其转化为u棵树的森林。根据之前的定义,我们可以将全体大小为p的无标号有根树编号为1,2,,cntp。对于某一个森林,将其每一棵树对应到这棵树所属类别的编号,我们可以将该森林与一个无序可重集合x~对应。将所有x~组成的集合记作X~

x~满足两个性质:恰好包含u个数,且每个数都在1cntp之间。也可以将at的概念从Sup+1,i迁移到x~上。不妨记ωx~为属于x~对应森林的带标号森林的数目的k次幂,那么fp,u可以表示为:

fp,u=x~X~(up)!k(p!)uk(t=1m1at!k)ωx~()=(up)!k(p!)uk(x~X~(t=1m1at!k)ωx~)

因为在分配完标号以后,树的同构就转化为了森林的同构。

然而,由于x~是无序可重集合,这非常不利于枚举,因此直接进行计算也非常麻烦。希望能将其转化为有序可重集合(即一个长度为u的序列)再进一步解决问题。

那么设x是一个长度为u的序列,且每一个数都在1cntp之间。将所有这样的x的集合记做X。如果x无序化后能和某一个x~相同,我们称x对应到x~

由于x~是一个可重的集合,因此对应到x~x的数目是变化的,不能直接枚举x。想要利用X得到一个和()相类似的等式,还需要借助置换群。

为了表达方便,用前置知识中的术语来表达。设G是所有长度为u的置换构成的群,将G作用于X

那么对于一个Orbit(x),所有在这一集合内的y都对应到相同的x~,可以用Orbit(x)来代替x~。将atω的概念迁移到x上,我们可以得到与()类似的式子:

fp,u=(up)!k(p!)uk(xX(t=1m1at!k)ωx|Orbit(x)|)

不难发现|Orbit(x)|=u!t=1mat!。此时有一个难点,就是ωx的计算。先尝试将所有a相同的x发在一起计算(此时(t=1m1at!k)|Orbit(x)|是相同的)。也就是说,此时的森林要求有m种不同的树,第iai棵。首先考虑m=1的情况,也就是需要u棵同构的树,不难发现这就等同于:

i=1cntp(|Sp,i|u)k=i=1cntp|Sp,i|uk

看上去似乎并未计算过这个式子,为了计算可能需要修改状态。那么先搁置一边,考虑m>1的情况,我们能否直接用下面的式子:

()t=1m(i=1cntp|Sp,i|atk)

计算呢?不可行,因为这并不能排除不同的两组得到同一类树的情况,同时也没有考虑组与组的数目相同时地位等价的问题。

但这样的思考并不是毫无意义的。不难发现,如果组与组之间默认为地位不等,且不同的组可以使用相同的一类树,那么()就是正确的。

最关键的一点是,这两个条件似乎与某一置换下的不动点有异曲同工之妙。我们考虑fG,则fix(f)就是f的不动点集合。f是由若干个置换环组成的,设有m个置换环,并设置换环的大小分别为a1,a2,,am。可以发现,如果xf的不动点,那么有与之前的a类似的性质,同一置换环内的位置上,树的种类必须相同。但是,由于置换环本身位置不同,每个置换环就是地位不等的(这也是有序序列的一个好处)。并且,由于我们只要求其为不动点即可,并不需要每个置换环的树种类各不相同,这就完美的符合我们之前的两个条件。

因此我们就可以利用()了,也就是说:

xfix(f)ωx=t=1m(i=1cntp|Sp,i|atk)

不过还有一个问题没有解决:怎么求i=1cntp|Sp,i|atk?它的形式和dpp相似,但是指数增加了at倍。必须先进一步扩张状态才能解决这个问题。

那么增加一个指标j,表示指标扩张的倍数。即:

dpn,j=i=1cntn|Sn,i|jktmpn,j,p=i=1cntn[mxs(Sn,i)p]|Sn,i|jkfp,j,u=i=1cntup+1[mns(Sup+1,i)=mxs(Sup+1,i)=p]|Sup+1,i|jk

相应修改转移方程:

tmpn,j,p=u=0n1p(n1up)jktmpnup,j,p1fp,j,ufp,j,u=(up)!jk(p!)ujk(xX(t=1m1at!jk)ωx|Orbit(x)|)

则:

xfix(f)ωx=t=1m(i=1cntp|Sp,i|atjk)=t=1mdpp,atj

注意ωx也是和j相关的。

首先考虑一下状态数量问题,可以发现由于atnp,因此这两维的乘积不会超过全局的n,因此只有i=1nni=O(nlogn)种可能。

还有一个问题是,我们并不只是简单的求xXωx,而是有一个(t=1m1at!jk)1|Orbit(x)|的系数,不能这样直接交换求和顺序。

那要通过什么方式转化呢?我们设置换f的某个权值为wf,那么有如下等式:

xXωx(fSG(x)wf)=fGwf(xfix(f)ωx)

只是交换了求和顺序,显然成立。这个等式的左边和xX(t=1m1at!jk)ωx|Orbit(x)|相似,右边和xfix(f)ωx相似,尝试利用这个等式来对目标进行转化。

如果能找到某种权重函数w,使得等式:

fSG(x)wf=C(t=1m1at!jk)1|Orbit(x)|

成立,其中C是一个常数,那么就有:

xX(t=1m1at!jk)ωx|Orbit(x)|=1CxXωx(fSG(x)wf)=1CfGwf(xfix(f)ωx)()=1CfGwf(t=1mdpp,atj)

由于后方的连乘只和置换环大小情况有关,那么自然也希望权重函数也之和置换环大小有关,而且最好也是连乘形式,即:

wf=t=1mw~at

如果可行,那么可以继续转化()式:

=1CfG(t=1mw~at)(t=1mdpp,atj)=1CfG(t=1mw~atdpp,atj)

则每个置换的结果都只和其置换环分解的大小分布情况有关,可以换一种求和方式,令hi=w~idpp,ij,枚举置换环的大小分布,并分配标号:

=1CfG(t=1mhat)=1Cl>01l!(t=1lbt=u(ub1,b2,,bl)(t=1l(bt1)!)(t=1lhbt))=u!Cl>01l!(t=1lbt=u(t=1lhbtbt))

似乎转化为了熟悉的式子。设生成函数H(x)=i>0hiixi,那么前面的式子就转化为:

=u!Cl>01l!(t=1lbt=u(t=1l[xbt]H(x)))=u!Cl>0[xu]Hl(x)l!=u!C[xu]eH(x)

好的!也就是说,我们现在有:

fp,j,u=(up)!jk(p!)ujk(xX(t=1m1at!jk)ωx|Orbit(x)|)=(up)!jk(p!)ujku!C[xu]eH(x)

唯一的问题就是计算权重函数w~了。回顾一下,我们是希望满足这个等式:

fSG(x)wf=fSG(x)(t=1mw~at)=C(t=1m1at!jk)1|Orbit(x)|

展开|Orbit(x)|,即:

fSG(x)(t=1mw~at)=C(t=1m1at!jk)t=1mat!u!

对于x,它的稳定化子就是满足仅在相同种类树之间进行置换的集合,就是说,只能在同种树内部进行置换环的拆解。那么模仿之前对置换环的枚举方法,换一种方式计算等式左边的值,只是换成了在每一类树内部:

=t=1m(l>01l!(t=1lbt=at(atb1,b2,,bl)(t=1l(bt1)!)(t=1lw~bt)))=t=1mat!(l>01l!(t=1lbt=at(t=1lw~btbt)))

同之前,设W(x)=i>0w~iixi,那么上方等式继续转化:

=t=1mat![xat]eW(x)

带回原等式,即为:

t=1mat![xat]eW(x)=C(t=1m1at!jk)t=1mat!u!

消去t=1mat!

t=1m[xat]eW(x)=(t=1m1at!jk)Cu!

显然我们令C=u!,那么有[xi]eW(x)=1i!jkeW(x)就是一个已知的多项式。通过W(x)=lneW(x)就可以求解出w~了。

回顾一下过程,可以计算出复杂度是O(n2logn)。由于多项式lnexp不是瓶颈,可以用简洁的O(n2)算法来计算。