$O(n^3)$ 的暴力 $ ext{DP}$ 比较好想,但是貌似无法优化了
考虑既然有如此强的限制,要求每一条边都被覆盖过,可以尝试使用容斥
设 $E$ 为没有覆盖到的边集, $F(E)$ 为 $E$ 中的边没有覆盖到(其他不管)的整棵树的方案数
于是用 $E$ 相当于将这棵树分割成了许多联通块,每个联通块里面只能选自己联通块的,那么每个联通块的方案数为
$h(size)=(size-1) imes (size-3) imes ... imes 3 imes 1$ (前提是 $2 mid size$ ,不然方案数显然为 $0$ )
于是我们可以换种方式 $ ext{DP}$
设 $f_{i,j}$ 为以 $i$ 为根的子树内 $i$ 所在的联通块大小为 $j$ 的方案数(不删掉 $i$ 所在的联通块)
所以转移就按容斥一样转移,如果删掉一棵子树,那就要减去删掉的方案数(差不多是这个意思),否则直接加上方案数
最后答案显然就是
$sumlimits_{i=2}^n f_{1,i} imes h(i)$
$code$ :
#include<cstdio> #include<cctype> #define maxn 5555 #define mod 1000000007 template<class T> inline T read(){ T r=0,f=0; char c; while(!isdigit(c=getchar()))f|=(c=='-'); while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar(); return f?-r:r; } template<class T> inline T min(T a,T b){ return a<b?a:b; } struct E{ int v,nxt; E() {} E(int v,int nxt):v(v),nxt(nxt) {} }e[maxn<<1]; int n,s_e,head[maxn],size[maxn]; long long ans,h[maxn],g[maxn],f[maxn][maxn]; inline void a_e(int u,int v){ e[++s_e]=E(v,head[u]); head[u]=s_e; } void dfs(int u,int fa){ f[u][1]=1; size[u]=1; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].v; if(v==fa)continue; dfs(v,u); for(int j=1;j<=size[u]+size[v];j++)g[j]=0; for(int j=1;j<=size[u];j++) for(int k=1;k<=size[v];k++){ (g[j]+=(mod-f[u][j]*f[v][k]%mod*h[k])%mod)%=mod;//删掉v这棵子树里的,所以要减去 (g[j+k]+=f[u][j]*f[v][k]%mod)%=mod;//不然直接累加 } for(int j=1;j<=size[u]+size[v];j++)f[u][j]=g[j]; size[u]+=size[v]; } } int main(){ n=read<int>(); for(int i=1;i<n;i++){ int u=read<int>(),v=read<int>(); a_e(u,v),a_e(v,u); } h[0]=1; for(int i=2;i<=n;i+=2) h[i]=h[i-2]*(i-1)%mod; dfs(1,0); ans=0; for(int i=2;i<=n;i+=2) (ans+=f[1][i]*h[i]%mod)%=mod; printf("%lld ",ans); return 0; }