// ---------- begin Tree DP ----------
struct TreeDP<Edge, Value, Init, Merge> {
    size: usize,
    graph: Vec<Vec<(usize, Edge)>>,
    init: Init,
    merge: Merge,
    phantom: std::marker::PhantomData<Value>,
}

impl<Edge, Value, Init, Merge> TreeDP<Edge, Value, Init, Merge>
where Edge: Clone,
      Value: Clone,
      Init: Fn(usize) -> Value,
      Merge: Fn(Value, Value, &Edge) -> Value,
{
    fn new(size: usize, init: Init, merge: Merge) -> Self {
        TreeDP {
            size: size,
            graph: vec![vec![]; size],
            init: init,
            merge: merge,
            phantom: std::marker::PhantomData,
        }
    }
    fn add_edge(&mut self, a: usize, b: usize, c: Edge) {
        assert!(a < self.size && b < self.size && a != b);
        self.graph[a].push((b, c.clone()));
        self.graph[b].push((a, c));
    }
    fn solve(&self, root: usize) -> Value {
        let size = self.size;
        let graph = &self.graph;
        let mut topo = vec![];
        let mut parent = vec![root; size];
        let mut stack = vec![root];
        while let Some(v) = stack.pop() {
            topo.push(v);
            for e in graph[v].iter() {
                if e.0 != parent[v] {
                    parent[e.0] = v;
                    stack.push(e.0);
                }
            }
        }
        assert!(topo.len() == size);
        let mut dp: Vec<Option<Value>> = (0..size).map(|_| None).collect();
        for &v in topo.iter().rev() {
            let mut now = (self.init)(v);
            for u in graph[v].iter() {
                if u.0 == parent[v] {
                    continue;
                }
                let b = dp[u.0].take().unwrap();
                now = (self.merge)(now, b, &u.1);
            }
            dp[v] = Some(now);
        }
        dp[root].take().unwrap()
    }
}
// ---------- end Tree DP ----------
//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

//

fn run() {
    input! {
        n: usize,
        e: [(usize1, usize1); n - 1],
    }
    const MOD: u64 = 1_000_000_007;
    let mut way = vec![0u64; n + 1];
    way[2] = 1;
    for i in 4..(n + 1) {
        if i % 2 == 0 {
            way[i] = way[i - 2] * (i - 1) as u64 % MOD;
        }
    }
    type Value = Vec<u64>;
    type Edge = ();
    let init = |_v: usize| {
        vec![1]
    };
    let merge = |a: Value, b: Value, _c: &Edge| -> Value {
        let mut next = vec![0u64; a.len() + b.len()];
        for (i, &a) in a.iter().enumerate() {
            if a == 0 {
                continue;
            }
            for (j, &b) in b.iter().enumerate().filter(|b| *b.1 != 0) {
                let x = a * b % MOD;
                next[i + j + 1] += x;
                if next[i + j + 1] >= MOD {
                    next[i + j + 1] -= MOD;
                }
                next[i] = (next[i] + (MOD - x) * way[j + 1]) % MOD;
            }
        }
        next
    };
    let mut solver = TreeDP::new(n, init, merge);
    for (a, b) in e {
        solver.add_edge(a, b, ());
    }
    let res = solver.solve(0);
    let mut ans = 0;
    for (i, a) in res.iter().enumerate() {
        ans += *a * way[i + 1] % MOD;
    }
    ans %= MOD;
    println!("{}", ans);
}

fn main() {
    run();
}


Measured memory_bytes: 6396