#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#define sqr(x)(x)*(x)
#define fz1(i,n) for (i=1;i<=n;i++)
#define fd1(i,n) for (i=n;i>=1;i--)
#define fz0g(i,n) for (i=0;i<=n;i++)
#define fd0g(i,n) for (i=n;i>=0;i--)
#define fz0k(i,n) for (i=0;i<n;i++)
#define fd0k(i,n) for (i=(long long)(n-1);i>=0;i--)
#define fz(i,x,y) for (i=x;i<=y;i++)
#define fd(i,y,x) for (i=y;i>=x;i--)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define rdst(st,len){char ss[len];scanf("%s",ss);(st)=ss;}
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#pragma GCC optimize(5)
#pragma GCC optimize(6)
#pragma GCC optimize(7)
#pragma GCC optimize(8)
#pragma GCC optimize(9)
using namespace std;
//struct bit{T_ arr[1000005];int lowbit(int x){return x&(-x);}void add(int x,T_ y){for (int i=x;i<=n;i+=lowbit(i)) arr[i]+=y;}T_ query(int x){T_ s=0;for (int i=x;i>0;i-=lowbit(i)) s+=arr[i];return s;}};
//struct seg{struct treedot{int l,r;T_ sum,add;void update(T_ x){sum+=(r-l+1)*x; add+=x;}}c[800005];void pushdown(int id){if (c[id].add){c[id*2].update(c[id].add);c[id*2+1].update(c[id].add);c[id].add=0;}}void pushup(int id){c[id].sum=c[id*2].sum+c[id*2+1].sum;}void build(int id,int l,int r){c[id].l=l;c[id].r=r;c[id].sum=0;c[id].add=0;if (l==r) c[id].sum=0;else{int mid=l+(r-l)/2;build(id*2,l,mid);build(id*2+1,mid+1,r);pushup(id);}}void update(int id,int le,int ri,int x){if (le>c[id].r||ri<c[id].l) return;if (le<=c[id].l&&c[id].r<=ri) c[id].update(x);else{pushdown(id);update(id*2,le,ri,x);update(id*2+1,le,ri,x);pushup(id);}}T_ query(int id,int le,int ri){if (ri<c[id].l||c[id].r<le) return 0;if (le<=c[id].l&&c[id].r<=ri) return c[id].sum;T_ ans=0;pushdown(id);ans+=query(id*2,le,ri);ans+=query(id*2+1,le,ri);pushup(id);return ans;}};
int n,m,i,j,mod=1e9+7,dp[5005][5005][2],sz[5005],x,y,ffac[5005],f[5005][2],ans;
vector<int> bi[5005],t;
bool cmp(int x,int y)
{
	return sz[x]<sz[y];
}
void dfs1(int x,int fa)
{
	sz[x]=1;
	ff(bi[x],it)
	{
		if (*it==fa) continue;
		dfs1(*it,x);
		sz[x]+=sz[*it];
	}
	t.clear();
	ff(bi[x],it)
	{
		if (*it==fa) continue;
		t.push_back(*it);
	}
	bi[x]=t;
}
void dfs2(int x)
{
	int s=0,i,j,k,l;
	dp[x][0][0]=1;
	ff(bi[x],it)
	{
		dfs2(*it);
		for (i=0;i<=s+sz[*it];i++) f[i][0]=f[i][1]=0;
		for (i=0;i<=s;i++)
		{
			for (j=0;j<=sz[*it];j++)
			{
				f[i+j][0]+=1ll*dp[x][i][0]*dp[*it][j][0]%mod;
				if (f[i+j][0]>=mod) f[i+j][0]-=mod;
				f[i+j][0]+=1ll*dp[x][i][1]*dp[*it][j][1]%mod;
				if (f[i+j][0]>=mod) f[i+j][0]-=mod;
				f[i+j][1]+=1ll*dp[x][i][0]*dp[*it][j][1]%mod;
				if (f[i+j][1]>=mod) f[i+j][1]-=mod;
				f[i+j][1]+=1ll*dp[x][i][1]*dp[*it][j][0]%mod;
				if (f[i+j][1]>=mod) f[i+j][1]-=mod;
			}
		}
		for (i=0;i<=s+sz[*it];i++) dp[x][i][0]=f[i][0];
		for (i=0;i<=s+sz[*it];i++) dp[x][i][1]=f[i][1];
		s+=sz[*it];
	}
	if (x>1)
	{
		for (i=s;i>=0;i--)
		{
			dp[x][sz[x]][0]+=1ll*dp[x][i][1]*ffac[sz[x]-i]%mod;
			if (dp[x][sz[x]][0]>=mod) dp[x][sz[x]][0]-=mod;
			dp[x][sz[x]][1]+=1ll*dp[x][i][0]*ffac[sz[x]-i]%mod;
			if (dp[x][sz[x]][1]>=mod) dp[x][sz[x]][1]-=mod;
		}
	}
}
int main()
{
	scanf("%d",&n);
	ffac[0]=1;
	for (i=2;i<=n;i+=2)
	{
		ffac[i]=1ll*ffac[i-2]*(i-1)%mod;
	}
	fz1(i,n-1)
	{
		scanf("%d%d",&x,&y);
		bi[x].push_back(y);
		bi[y].push_back(x);
	}
	dfs1(1,0);
	fz1(i,n) sort(bi[i].begin(),bi[i].end(),cmp); 
	dfs2(1);
	for (i=n;i>=0;i--)
	{
		ans+=1ll*dp[1][i][0]*ffac[n-i]%mod;
		if (ans>=mod) ans-=mod;
		ans-=1ll*dp[1][i][1]*ffac[n-i]%mod;
		if (ans<0) ans+=mod;
	}
	cout<<ans<<endl;
	return 0;
}

Measured memory_bytes: 195200