[DP记录]AT4352 [ARC101C] Ribbons on Tree
command_block · · 个人记录
题意 : 给定一棵
给树上的点两两配对,对于一对
定义一个配对方案合法当且仅当所有边都有颜色。求合法配对方案数,答案对
转移 :
复杂度为
以上
钦定边集
考虑钦定边集
于是,记
记
边界 :
转移 :
其中,
最终答案即为
根据树形背包,复杂度为
#include<algorithm>
#include<cstdio>
#include<vector>
#define pb push_back
#define MaxN 5050
using namespace std;
const int mod=1000000007;
vector<int> g[MaxN];
int ans,f[MaxN][MaxN],t[MaxN],s[MaxN],w[MaxN],siz[MaxN];
void dfs(int u)
{
siz[u]=1;f[u][1]=1;
for (int i=0,v;i<g[u].size();i++)
if (!siz[v=g[u][i]]){
dfs(v);
for (int k1=1;k1<=siz[u];k1++)
for (int k2=1;k2<=siz[v];k2++)
s[k1+k2]=(s[k1+k2]+1ll*f[u][k1]*f[v][k2])%mod;
siz[u]+=siz[v];
for (int k=1;k<=siz[u];k++)
{f[u][k]=(s[k]-1ll*f[u][k]*t[v])%mod;s[k]=0;}
}
for (int k=1;k<=siz[u];k++)
t[u]=(t[u]+1ll*f[u][k]*w[k])%mod;
}
int n;
int main()
{
scanf("%d",&n);
w[2]=1;
for (int i=4;i<=n;i+=2)
w[i]=1ll*w[i-2]*(i-1)%mod;
for (int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
g[u].pb(v);g[v].pb(u);
}dfs(1);
printf("%d",(t[1]+mod)%mod);
return 0;
}