ARC101C 题解
首先可以很容易想到一个
发现这个
题目中要求的是恰好所有边都被经过,即恰好有
考虑如何求
定义
所以对于一个
接下来我们可以考虑继续在树上
定义
然后子树归并,转移是决策
特别的,根据定义和转移,我们发现
最后特殊考虑一下根节点,因为它没有
因为只剩下了子树归并,所以复杂度是
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn = 5e3 + 50, INF = 0x3f3f3f3f, mod = 1e9 + 7;
inline int read () {
register int x = 0, w = 1;
register char ch = getchar ();
for (; ch < '0' || ch > '9'; ch = getchar ()) if (ch == '-') w = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar ()) x = x * 10 + ch - '0';
return x * w;
}
inline int addmod (register int a, register int b) {
return a += b, a >= mod ? a - mod : a;
}
inline ll mulmod (register ll a, register int b) {
return a *= b, a >= mod ? a % mod : a;
}
int n;
struct Edge {
int to, next;
} e[maxn << 1];
int tot, head[maxn];
inline void Add (register int u, register int v) {
e[++ tot].to = v;
e[tot].next = head[u];
head[u] = tot;
}
int siz[maxn], f[maxn][maxn], g[maxn], p[maxn];
inline void Init () {
g[0] = 1;
for (register int i = 2; i <= n; i += 2)
g[i] = mulmod (g[i - 2], i - 1);
}
inline void DFS (register int u, register int fa) {
siz[u] = 1, f[u][1] = 1;
for (register int i = head[u]; i; i = e[i].next) {
register int v = e[i].to;
if (v == fa) continue;
DFS (v, u);
for (register int j = 1; j <= siz[u] + siz[v]; j ++) p[j] = 0;
for (register int j = 1; j <= siz[u]; j ++)
for (register int k = 0; k <= siz[v]; k ++)
p[j + k] = addmod (p[j + k], mulmod (f[u][j], f[v][k]));
for (register int j = 1; j <= siz[u] + siz[v]; j ++) f[u][j] = p[j];
siz[u] += siz[v];
}
for (register int j = 1; j <= siz[u]; j ++)
f[u][0] = addmod (f[u][0], mulmod (f[u][j], g[j]));
f[u][0] = mod - f[u][0];
}
int main () {
n = read(), Init ();
for (register int i = 1, u, v; i < n; i ++)
u = read(), v = read(), Add (u, v), Add (v, u);
DFS (1, 0), printf ("%d\n", mod - f[1][0]);
return 0;
}