树上计数
考虑如果一个点的亲儿子是偶数个 两两亲儿子配对就好
如果一个点的亲儿子是奇数个 挑一个出来和连上父亲 其余偶数个两两配对
n个两两配对的方案数为 (C(n,2)×C(n-2,2)×...×C(2,2))/((n/2)!)
化简得 (n!)/(2的n/2次方)×((n/2)!)预处理阶乘就好
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int mod=998244353;
const int maxn=1e5+5;
int n;
vector<int>Q[maxn];
ll ans=1;
ll dp[maxn],jc[maxn],vis[maxn],cf[maxn];
ll fast_mi(ll aa, ll bb){
ll res=1;
while(bb){
if(bb&1)res=res*aa%mod;
bb>>=1;
aa=aa*aa%mod;
}
return res;
}
void dfs(int u,int fa);
ll calc(ll x){
return jc[x]*fast_mi(cf[x/2]*jc[x/2]%mod,mod-2)%mod;
}
int main(){
int n;
jc[0]=1;
cf[0]=1;
cin>>n;
for(int i=1;i<n;i++){
jc[i]=jc[i-1]*i%mod;
cf[i]=cf[i-1]*2%mod;
int a,b;
cin>>a>>b;
Q[a].push_back(b);
Q[b].push_back(a);
}
jc[n]=jc[n-1]*n%mod;
cf[n]=cf[n-1]*2%mod;
dfs(1,1);
for(int i=1;i<=n;i++)
ans=ans*dp[i]%mod;
cout<<ans<<endl;
return 0;
}
void dfs(int u,int fa){
ll res=0;
ll sz=Q[u].size()-1;
for(int i=0;i<Q[u].size();i++){
int to=Q[u][i];
if(to==fa)continue;
dfs(to,u);
res+=vis[to];
}
if(u==1)sz++;
ll t=sz-res;
if(t&1){
dp[u]=t*calc(t-1)%mod;
vis[u]=1;
}else
dp[u]=calc(t);
}