其他分享
首页 > 其他分享> > [atARC121E]Directed Tree

[atARC121E]Directed Tree

作者:互联网

令$b_{a_{i}}=i$,那么问题即要求$i$不是$b_{i}$的祖先,也即$b_{i}$不严格在$i$的子树中

显然$a_{i}$和$b_{i}$一一对应,因此我们不妨统计$b_{i}$的个数

考虑容斥,令$f(S)$为$\forall i\in S,b_{i}$严格在$i$子树中的排列数,根据容斥答案即$\sum_{S\subseteq [1,n]}(-1)^{|S|}f(S)$

关于$f(S)$,可以从底往上依次确定$i\in S$的$b_{i}$,方案数即$\prod_{i\in S}sz_{i}-\sum_{x\in S且x在i的子树中}1$(其中$sz_{i}$为$i$的子树大小),最后对于$i\not\in S$的$b_{i}$没有限制,即$(n-|S|)!$种

对于后者,可以在树形dp中记录,即令$f_{i,j}$表示以$i$为根的子树中$\sum_{x\in S且x在i的子树中}1=j$的排列数,最终不难得到答案即$\sum_{i=1}^{n}(-1)^{i}(n-i)!f_{1,i}$

转移方程即$f_{i,j+k}=\sum f_{i,j}f_{son,k}$,最终再将$i$加入$S$,即$f_{i,j}=f_{i,j}+(sz_{i}-j)f_{i,j-1}$

时间复杂度为$o(n^{2})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 2005
 4 #define mod 998244353
 5 struct Edge{
 6     int nex,to;
 7 }edge[N];
 8 int E,n,x,ans,head[N],sz[N],g[N],f[N][N];
 9 void add(int x,int y){
10     edge[E].nex=head[x];
11     edge[E].to=y;
12     head[x]=E++;
13 }
14 void dfs(int k){
15     f[k][0]=1;
16     for(int i=head[k];i!=-1;i=edge[i].nex){
17         dfs(edge[i].to);
18         memcpy(g,f[k],sizeof(g));
19         memset(f[k],0,sizeof(f[k])); 
20         for(int j=0;j<=sz[k];j++)
21             for(int l=0;l<=sz[edge[i].to];l++)f[k][j+l]=(f[k][j+l]+1LL*g[j]*f[edge[i].to][l])%mod;
22         sz[k]+=sz[edge[i].to];
23     }
24     sz[k]++;
25     for(int i=sz[k];i;i--)f[k][i]=(f[k][i]+1LL*(sz[k]-i)*f[k][i-1])%mod;
26 }
27 int main(){
28     scanf("%d",&n);
29     memset(head,-1,sizeof(head));
30     for(int i=2;i<=n;i++){
31         scanf("%d",&x);
32         add(x,i);
33     }
34     dfs(1);
35     for(int i=0;i<=n;i++){
36         int s=1;
37         if (i&1)s=mod-1;
38         for(int j=1;j<=n-i;j++)s=1LL*s*j%mod;
39         ans=(ans+1LL*s*f[1][i])%mod;
40     }
41     printf("%d",ans);
42 }
View Code

 

标签:Directed,sz,head,atARC121E,int,sum,Tree,子树中,edge
来源: https://www.cnblogs.com/PYWBKTDA/p/14973642.html