#include <bits/stdc++.h>

using namespace std;
using int64 = long long;

constexpr int DEBUG = 0;

struct Edge {
  const int from, to;
  Edge(int from, int to) : from(from), to(to) {}
};

vector<vector<Edge>> ReadUndirectedGraph(
    int n, int m, bool is_one_indexed=false) {
  vector<vector<Edge>> graph(n);
  for (int i = 0; i < m; i++) {
    int v1, v2;
    cin >> v1 >> v2;
    if (is_one_indexed) {
      v1--;
      v2--;
    }
    graph[v1].push_back(Edge(v1, v2));
    graph[v2].push_back(Edge(v2, v1));
  }
  return graph;
}

constexpr int64 P = 1000000007;

struct FiniteField {
 private:
  int64 x;
 public:
  FiniteField(int64 x) : x(x) {
    if (x > P || x < 0) { cerr << "Invalied FiniteField!" << endl; exit(1); }
  }
  FiniteField() : x(0) {}
  int64 Value() const { return x; }
  inline FiniteField operator+(FiniteField o) const {
    FiniteField r(*this); r += o; return r;
  }
  inline FiniteField operator-(FiniteField o) const {
    FiniteField r(*this); r -= o; return r;
  }
  inline FiniteField operator* (FiniteField o) const {
    FiniteField r(*this); r *= o; return r;
  }
  inline FiniteField operator/ (FiniteField o) const {
    FiniteField r(*this); r /= o; return r;
  }
  inline void operator+= (FiniteField o) { x = (x + o.x) % P; }
  inline void operator-= (FiniteField o) { x = (x + P - o.x) % P; }
  inline void operator*= (FiniteField o) { x = (x * o.x) % P; }
  void operator/=(FiniteField o) {
    int64 p = P - 2; while (p) { if (p % 2) { *this *= o; } o *= o; p /= 2; }
  }
};

template<typename T>
vector<vector<T>> Make2DVector(int d1, int d2, T default_value) {
  return vector<vector<T>>(d1, vector<T>(d2, default_value));
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  cin >> n;
  auto graph = ReadUndirectedGraph(n, n - 1, true);

  vector<FiniteField> table(n + 1);
  table[0] = 1;
  for (int i = 2; i <= n; i += 2) {
    table[i] = table[i - 2] * (i - 1);
    // cout << "i: " << i << " " << table[i].Value() << endl;
  }

  auto merge_fn = [&](
      const vector<vector<FiniteField>>& p,
      const vector<vector<FiniteField>>& c)
      -> vector<vector<FiniteField>> {
    int d1 = p.size() - 1;
    int d2 = c.size() - 1;
    vector<vector<FiniteField>> r = Make2DVector(d1 + d2 + 1, 2, FiniteField(0));
    for (int s1 = 1; s1 <= d1; s1++) {
      for (int s2 = 1; s2 <= d2; s2++) {
        for (int p1 = 0; p1 < 2; p1++) {
          for (int p2 = 0; p2 < 2; p2++) {
            // Don't conver an edge.
            {
              int p3 = (p1 + p2 + 1) % 2;
              r[s1][p3] += p[s1][p1] * c[s2][p2] * table[s2];
            }

            // Cover an edge.
            {
              int p3 = (p1 + p2) % 2;
              r[s1 + s2][p3] += p[s1][p1] * c[s2][p2];
            }
          }
        }
      }
    }
    return r;
  };

  vector<vector<vector<FiniteField>>> dp(n);
  function<void(int, int)> dfs_fn = [&](int v, int p) {
    vector<int> cs;
    for (const auto& e : graph[v]) {
      if (e.to == p) continue;
      cs.push_back(e.to);
    }

    dp[v] = Make2DVector(2, 2, FiniteField(0));
    dp[v][1][0] = 1;
    if (cs.empty()) return;

    for (int c : cs) {
      dfs_fn(c, v);
      dp[v] = merge_fn(dp[v], dp[c]);
    }
  };
  dfs_fn(0, -1);

  FiniteField ans = 0;
  for (int i = 1; i <= n; i++) {
    ans += dp[0][i][0] * table[i];
    ans -= dp[0][i][1] * table[i];
  }
  cout << ans.Value() << endl;
}

Measured memory_bytes: 480768