题意:给 m m m 棵树,树之间是完全图,问哈密顿回路的数量
我们考虑到最后的哈密顿回路一定是有一段一段的树链串起来得到的
相当于每一棵树拆分成若干条树链,大小不限个数不限,所有的拼接起来,要求相邻的不来自同一颗树
我们可以树形 d p dp dp 求出一棵树分成 j j j 条链的方案数,这里带方向
接着,我们先不考虑环,只考虑序列,问题转换为有 m m m 种颜色的球,每种求有若干个,求最后拼接起来没有相邻颜色相同的个数
我们对每一种颜色钦定它至少有多少个相同要相邻来容斥,我们将相邻的合并后和其它颜色拼接
直接构造每一种颜色的
E
G
F
EGF
EGF,枚举合并过后的大小
F i ( x ) = ∑ j = 1 n f [ i ] [ j ] ∗ j ! ∑ k = 1 j ( j − 1 k − 1 ) ( − 1 ) j − k x k k ! F_i(x)=\sum_{j=1}^nf[i][j]*j!\sum_{k=1}^{j}\binom{j-1}{k-1}(-1)^{j-k}\frac{x^k}{k!} Fi(x)=j=1∑nf[i][j]∗j!k=1∑j(k−1j−1)(−1)j−kk!xk
考虑环的情况怎么做,第一个强行是 1 所在的链, 有
E
G
F
EGF
EGF:
F
1
(
x
)
=
∑
j
=
1
n
f
[
i
]
[
j
]
(
j
−
1
)
!
∑
k
=
1
j
(
j
−
1
k
−
1
)
(
−
1
)
j
−
k
x
k
−
1
(
k
−
1
)
!
F_1(x)=\sum_{j=1}^nf[i][j](j-1)!\sum_{k=1}^j\binom{j-1}{k-1}(-1)^{j-k}\frac{x^{k-1}}{(k-1)!}
F1(x)=j=1∑nf[i][j](j−1)!k=1∑j(k−1j−1)(−1)j−k(k−1)!xk−1
减去不合法的情况,钦定最后一个在第一棵树上,那么要减去:
F
1
′
(
x
)
=
∑
j
=
1
n
f
[
i
]
[
j
]
(
j
−
1
)
!
∑
k
=
2
j
(
j
−
1
k
−
1
)
(
−
1
)
j
−
k
x
k
−
2
(
k
−
2
)
!
F_1'(x)=\sum_{j=1}^nf[i][j](j-1)!\sum_{k=2}^j\binom{j-1}{k-1}(-1)^{j-k}\frac{x^{k-2}}{(k-2)!}
F1′(x)=j=1∑nf[i][j](j−1)!k=2∑j(k−1j−1)(−1)j−k(k−2)!xk−2
暴力乘起来就可以了
树形DP,考虑
f
[
i
]
[
j
]
[
0
/
1
/
2
]
f[i][j][0/1/2]
f[i][j][0/1/2] 表示到 i 选了 j 条链的方案数
0 表示
i
i
i 孤立,
1
1
1 表示 i 向下匹配,
2
2
2 表示有一条路径向上向下经过
i
i
i
这么做是为了处理
2
2
2 的系数
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 5e3 + 5;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
int first[N], nxt[N << 1], to[N << 1], tot;
void adde(int x, int y){ nxt[++tot] = first[x], first[x] = tot, to[tot] = y; }
cs int Mod = 998244353, inv2 = (Mod+1)>>1;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans; }
int fac[N], ifac[N]; int T, n, node;
int dp[N][N][3], sz[N];
int C(int n, int m){ if(n<0||m<0||n<m) return 0; return mul(fac[n], mul(ifac[m], ifac[n-m])); }
void prework(){
fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
for(int i = 2; i <= N-5; i++) fac[i] = mul(fac[i-1], i);
ifac[N-5] = ksm(fac[N-5], Mod-2);
for(int i = N-6; i >= 2; i--) ifac[i] = mul(ifac[i+1], i+1);
}
void Merge(int u, int v){
int a = sz[u], b = sz[v]; sz[u] += sz[v];
static int tp[N][3]; memset(tp, 0, sizeof(int) * (a+b+1) * 3);
for(int i = 1; i <= b; i++){
int all = add(dp[v][i][0], add(dp[v][i][1], dp[v][i][2]));
for(int j = 1; j <= a; j++){
Add(tp[i + j][0], mul(dp[u][j][0], all));
Add(tp[i + j][1], mul(dp[u][j][1], all));
Add(tp[i + j][2], mul(dp[u][j][2], all));
Add(tp[i + j - 1][1], mul(dp[u][j][0], add(dp[v][i][1], mul(dp[v][i][0], 2))));
Add(tp[i + j - 1][2], mul(dp[u][j][1], add(dp[v][i][0], mul(dp[v][i][1], inv2))));
}
} memcpy(dp[u], tp, sizeof(int) * (a+b+1) * 3);
}
void dfs(int u, int fa){
memset(dp[u], 0, sizeof(int) * (sz[u] + 1) * 3); sz[u] = dp[u][1][0] = 1;
for(int i = first[u]; i; i = nxt[i]) if(to[i]^fa) dfs(to[i], u), Merge(u, to[i]);
}
int ans[N], G[N];
void PolyMul(int a, int b){
static int tmp[N + N];
memset(tmp, 0, sizeof(int) * (a+b-1));
for(int i = 0; i < a; i++) for(int j = 0; j < b; j++)
Add(tmp[i + j], mul(ans[i], G[j]));
memcpy(ans, tmp, sizeof(int) * (a+b-1));
}
int main(){
T = read(); ans[0] = 1; prework();
while(T--){
int k = read(); tot = 0; memset(first, 0, sizeof(int) * (k+1));
for(int i = 1; i < k; i++){ int x = read(), y = read(); adde(x, y); adde(y, x); }
dfs(1, 0); static int ct[N];
for(int i = 1; i <= k; i++)
ct[i] = mul(T==0?fac[i-1]:fac[i], add(dp[1][i][0], add(dp[1][i][1], dp[1][i][2])));
for(int i = 1; i <= k; i++){
int coef = 0;
for(int j = i; j <= k; j++){
int vl = mul(ct[j], C(j-1, i-1));
(j-i)&1 ? Add(coef, Mod-vl) : Add(coef, vl);
} if(T == 0){
G[i-1] = coef; if(i > 1) Add(G[i-2], Mod-coef);
} else G[i] = coef;
} if(T == 0) G[k] = 0; else G[0] = 0;
for(int i = 0; i <= k; i++) Mul(G[i], ifac[i]);
PolyMul(node+1, k+1); node += k;
} int sum = 0;
for(int i = 0; i <= node; i++) Add(sum, mul(fac[i], ans[i]));
cout << sum; return 0;
}