#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stdio.h>
#include <utility>
#include <vector>
using namespace std;
#define y0 y0z
#define y1 y1z
#define yn ynz
#define j0 j0z
#define j1 j1z
#define jn jnz
#define tm tmz
#define buli(x) (__builtin_popcountll(x))
#define bur0(x) (__builtin_ctzll(x))
#define bul2(x) (63 - __builtin_clzll(x))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define fil(a, b) memset((a), (b), sizeof(a))
#define cl(a) fil(a, 0)
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define foreach(it, a)                                                         \\
  for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define rep(i, a, b) for (int i = (a), _ed = (b); i < _ed; i++)
#define per(i, a, b) for (int i = (b)-1, _ed = (a); i >= _ed; i--)
#define forg(i, gu) for (int i = gu; ~i; i = e[i].next)
#define pw(x) ((ll(1)) << (x))
#define upmo(a, b) (((a) = ((a) + (b)) % mo) < 0 ? (a) += mo : (a))
#define mmo(a, b) (((a) = 1ll * (a) * (b) % mo) < 0 ? (a) += mo : (a))
void getre() {
  int x = 0;
  printf("%d\\n", 1 / x);
}
void gettle() {
  int res = 1;
  while (1)
    res <<= 1;
  printf("%d\\n", res);
}
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;
template <typename T, typename S> inline bool upmin(T &a, const S &b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S> inline bool upmax(T &a, const S &b) {
  return a < b ? a = b, 1 : 0;
}
template <typename N, typename PN> inline N flo(N a, PN b) {
  return a >= 0 ? a / b : -((-a - 1) / b) - 1;
}
template <typename N, typename PN> inline N cei(N a, PN b) {
  return a > 0 ? (a - 1) / b + 1 : -(-a / b);
}
template <typename N> N gcd(N a, N b) { return b ? gcd(b, a % b) : a; }
template <typename N> inline int sgn(N a) {
  return a > 0 ? 1 : (a < 0 ? -1 : 0);
}
#if ((_WIN32 || __WIN32__) && __cplusplus < 201103L)
#define lld "%I64d"
#else
#define lld "%lld"
#endif
inline void gn(long long &x) {
  int sg = 1;
  char c;
  while (((c = getchar()) < '0' || c > '9') && c != '-')
    ;
  c == '-' ? (sg = -1, x = 0) : (x = c - '0');
  while ((c = getchar()) >= '0' && c <= '9')
    x = x * 10 + c - '0';
  x *= sg;
}
inline void gn(int &x) {
  long long t;
  gn(t);
  x = t;
}
inline void gn(unsigned long long &x) {
  long long t;
  gn(t);
  x = t;
}
inline void gn(double &x) {
  double t;
  scanf("%lf", &t);
  x = t;
}
inline void gn(long double &x) {
  double t;
  scanf("%lf", &t);
  x = t;
}
inline void gs(char *s) { scanf("%s", s); }
inline void gc(char &c) {
  while ((c = getchar()) > 126 || c < 33)
    ;
}
inline void pc(char c) { putchar(c); }
#ifdef JCVB
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
typedef long long ll;
typedef double db;
inline ll sqr(ll a) { return a * a; }
inline db sqrf(db a) { return a * a; }
const int inf = 0x3f3f3f3f;
// const ll inf=0x3f3f3f3f3f3f3f3fll;
const db pi = 3.14159265358979323846264338327950288L;
const db eps = 1e-6;
const int mo = 1e9 + 7;
// int qp(int a,ll b){int
// n=1;do{if(b&1)n=1ll*n*a%mo;a=1ll*a*a%mo;}while(b>>=1);return n;}

const int TREE_MAXV = 3000 + 5;
struct edge {
  int v, next;
} e[TREE_MAXV * 2];
int g[TREE_MAXV], etot;
int qu[TREE_MAXV], pre[TREE_MAXV];
int h[33333];
int n;
void ae(int u, int v) {
  e[etot].v = v;
  e[etot].next = g[u];
  g[u] = etot++;
}

int bel[33333];
void bfs(int rt) {
  int p = 0, q = 0;
  pre[rt] = 0;
  h[rt] = 0;
  qu[q++] = rt;
  while (p != q) {
    int u = qu[p++];
    for (int i = g[u]; ~i; i = e[i].next)
      if (e[i].v != pre[u]) {
        pre[e[i].v] = u;
        bel[e[i].v] |= bel[u];
        h[e[i].v] = h[u] + 1;
        qu[q++] = e[i].v;
      }
  }
}
void tree_init() {
  static bool ini = 0;
  if (!ini) {
    ini = 1;
    memset(g, -1, sizeof(g));
  } else {
    for (int i = 0; i <= n; i++)
      g[i] = -1;
  }
  etot = 0;
}
void readedge() {
  for (int i = 1; i < n; i++) {
    int x, y;
    gn(x);
    gn(y);
    ae(x, y);
    ae(y, x);
  }
}

int boun[2222], to[2222];
const int zer = 1111;
int f[1111][2222];

int dp() {
  cl(f);
  for (int i = n - 1; i >= 0; i--) {
    int u = qu[i];

    for (int j = to[u] - boun[u]; j <= to[u] + boun[u]; j++) {
      f[u][j + zer] = 1;
      forg(t, g[u]) if (e[t].v != pre[u])
          mmo(f[u][j + zer], (f[e[t].v][j - 1 + zer] + f[e[t].v][j + 1 + zer]));
    }
  }
  int ret = 0;
  rep(t, 0, 2222) upmo(ret, f[qu[0]][t]);
  return ret;
}

int main() {
#ifdef JCVB
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
  int _time_jc = clock();
#endif
  gn(n);
  tree_init();
  readedge();

  static int dis1[2222];

  bfs(1);
  int ma = 1;
  rep(u, 2, n + 1) if (h[u] > h[ma]) ma = u;
  bfs(ma);
  int mav = 1;
  rep(u, 1, n + 1) if (h[u] > h[mav]) mav = u;

  bfs(mav);
  rep(i, 1, n + 1) dis1[i] = h[i];
  bfs(ma);
  int r;

  r = cei(h[mav], 2);
  int rt = 0, rt2 = 0;

  if (h[mav] % 2 == 0) {
    rep(i, 1, n + 1) {
      if (dis1[i] == h[i] && h[i] == h[mav] / 2)
        rt = i;
    }
  } else {
    rep(i, 1, n + 1) {
      if (dis1[i] == h[mav] / 2 && h[i] == (h[mav] + 1) / 2)
        rt = i;
      if (dis1[i] == (h[mav] + 1) / 2 && h[i] == (h[mav] + 0) / 2)
        rt2 = i;
    }
  }

  bel[rt2] = 1;
  bfs(rt);

  int ans = 0;
  if (rt2 == 0) {
    getre();
    rep(u, 1, n + 1) boun[u] = r - h[u], to[u] = 0;
    upmo(ans, dp());
  } else {
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
      }
    }
    upmo(ans, dp());
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 1;
          boun[u] = 0;
        }
      }
    }
    upmo(ans, -dp());

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = -1;
          boun[u] = 0;
        }
      }
    }
    upmo(ans, -dp());

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d + 1;
      } else {
        to[u] = 0;
        boun[u] = d;
      }
    }
    upmo(ans, dp());

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (!bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 1;
          boun[u] = 0;
        }
      }
    }
    upmo(ans, -dp());

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (!bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = -1;
          boun[u] = 0;
        }
      }
    }
    upmo(ans, -dp());
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (!bel[u]) {
        to[u] = 1;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 0;
          boun[u] = 0;
        }
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 1;
          boun[u] = 0;
        }
      }
    }
    upmo(ans, dp());
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 1;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 0;
          boun[u] = 0;
        }
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 1;
          boun[u] = 0;
        }
      }
    }
    upmo(ans, dp());
  }

  printf("%d\\n", ans);
#ifdef JCVB
  debug("time: %d\\n", int(clock() - _time_jc));
#endif
  return 0;
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stdio.h>
#include <utility>
#include <vector>
using namespace std;
#define y0 y0z
#define y1 y1z
#define yn ynz
#define j0 j0z
#define j1 j1z
#define jn jnz
#define tm tmz
#define buli(x) (__builtin_popcountll(x))
#define bur0(x) (__builtin_ctzll(x))
#define bul2(x) (63 - __builtin_clzll(x))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define fil(a, b) memset((a), (b), sizeof(a))
#define cl(a) fil(a, 0)
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define foreach(it, a)                                                         \\
  for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define rep(i, a, b) for (int i = (a), _ed = (b); i < _ed; i++)
#define per(i, a, b) for (int i = (b)-1, _ed = (a); i >= _ed; i--)
#define forg(i, gu) for (int i = gu; ~i; i = e[i].next)
#define pw(x) ((ll(1)) << (x))
#define upmo(a, b) (((a) = ((a) + (b)) % mo) < 0 ? (a) += mo : (a))
#define mmo(a, b) (((a) = 1ll * (a) * (b) % mo) < 0 ? (a) += mo : (a))
void getre() {
  int x = 0;
  printf("%d\\n", 1 / x);
}
void gettle() {
  int res = 1;
  while (1)
    res <<= 1;
  printf("%d\\n", res);
}
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;
template <typename T, typename S> inline bool upmin(T &a, const S &b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S> inline bool upmax(T &a, const S &b) {
  return a < b ? a = b, 1 : 0;
}
template <typename N, typename PN> inline N flo(N a, PN b) {
  return a >= 0 ? a / b : -((-a - 1) / b) - 1;
}
template <typename N, typename PN> inline N cei(N a, PN b) {
  return a > 0 ? (a - 1) / b + 1 : -(-a / b);
}
template <typename N> N gcd(N a, N b) { return b ? gcd(b, a % b) : a; }
template <typename N> inline int sgn(N a) {
  return a > 0 ? 1 : (a < 0 ? -1 : 0);
}
#if ((_WIN32 || __WIN32__) && __cplusplus < 201103L)
#define lld "%I64d"
#else
#define lld "%lld"
#endif
inline void gn(long long &x) {
  int sg = 1;
  char c;
  while (((c = getchar()) < '0' || c > '9') && c != '-')
    ;
  c == '-' ? (sg = -1, x = 0) : (x = c - '0');
  while ((c = getchar()) >= '0' && c <= '9')
    x = x * 10 + c - '0';
  x *= sg;
}
inline void gn(int &x) {
  long long t;
  gn(t);
  x = t;
}
inline void gn(unsigned long long &x) {
  long long t;
  gn(t);
  x = t;
}
inline void gn(double &x) {
  double t;
  scanf("%lf", &t);
  x = t;
}
inline void gn(long double &x) {
  double t;
  scanf("%lf", &t);
  x = t;
}
inline void gs(char *s) { scanf("%s", s); }
inline void gc(char &c) {
  while ((c = getchar()) > 126 || c < 33)
    ;
}
inline void pc(char c) { putchar(c); }
#ifdef JCVB
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
typedef long long ll;
typedef double db;
inline ll sqr(ll a) { return a * a; }
inline db sqrf(db a) { return a * a; }
const int inf = 0x3f3f3f3f;
// const ll inf=0x3f3f3f3f3f3f3f3fll;
const db pi = 3.14159265358979323846264338327950288L;
const db eps = 1e-6;
const int mo = 1e9 + 7;
// int qp(int a,ll b){int
// n=1;do{if(b&1)n=1ll*n*a%mo;a=1ll*a*a%mo;}while(b>>=1);return n;}

const int TREE_MAXV = 3000 + 5;
struct edge {
  int v, next;
} e[TREE_MAXV * 2];
int g[TREE_MAXV], etot;
int qu[TREE_MAXV], pre[TREE_MAXV];
int h[33333];
int n;
void ae(int u, int v) {
  e[etot].v = v;
  e[etot].next = g[u];
  g[u] = etot++;
}

int bel[33333];
void bfs(int rt) {
  int p = 0, q = 0;
  pre[rt] = 0;
  h[rt] = 0;
  qu[q++] = rt;
  while (p != q) {
    int u = qu[p++];
    for (int i = g[u]; ~i; i = e[i].next)
      if (e[i].v != pre[u]) {
        pre[e[i].v] = u;
        bel[e[i].v] |= bel[u];
        h[e[i].v] = h[u] + 1;
        qu[q++] = e[i].v;
      }
  }
}
void tree_init() {
  static bool ini = 0;
  if (!ini) {
    ini = 1;
    memset(g, -1, sizeof(g));
  } else {
    for (int i = 0; i <= n; i++)
      g[i] = -1;
  }
  etot = 0;
}
void readedge() {
  for (int i = 1; i < n; i++) {
    int x, y;
    gn(x);
    gn(y);
    ae(x, y);
    ae(y, x);
  }
}

int boun[2222], to[2222];
const int zer = 1111;
int f[1111][2222];

int dp() {
  cl(f);
  for (int i = n - 1; i >= 0; i--) {
    int u = qu[i];

    for (int j = to[u] - boun[u]; j <= to[u] + boun[u]; j++) {
      f[u][j + zer] = 1;
      forg(t, g[u]) if (e[t].v != pre[u])
          mmo(f[u][j + zer], (f[e[t].v][j - 1 + zer] + f[e[t].v][j + 1 + zer]));
    }
  }
  int ret = 0;
  rep(t, 0, 2222) upmo(ret, f[qu[0]][t]);
  return ret;
}

int main() {
#ifdef JCVB
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
  int _time_jc = clock();
#endif
  gn(n);
  tree_init();
  readedge();

  static int dis1[2222];

  bfs(1);
  int ma = 1;
  rep(u, 2, n + 1) if (h[u] > h[ma]) ma = u;
  bfs(ma);
  int mav = 1;
  rep(u, 1, n + 1) if (h[u] > h[mav]) mav = u;

  bfs(mav);
  rep(i, 1, n + 1) dis1[i] = h[i];
  bfs(ma);
  int r;

  r = cei(h[mav], 2);
  int rt = 0, rt2 = 0;

  if (h[mav] % 2 == 0) {
    rep(i, 1, n + 1) {
      if (dis1[i] == h[i] && h[i] == h[mav] / 2)
        rt = i;
    }
  } else {
    rep(i, 1, n + 1) {
      if (dis1[i] == h[mav] / 2 && h[i] == (h[mav] + 1) / 2)
        rt = i;
      if (dis1[i] == (h[mav] + 1) / 2 && h[i] == (h[mav] + 0) / 2)
        rt2 = i;
    }
  }

  bel[rt2] = 1;
  bfs(rt);

  int ans = 0;
  if (rt2 == 0) {
    rep(u, 1, n + 1) boun[u] = r - h[u], to[u] = 0;
    upmo(ans, dp());
  } else {
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
      }
    }
    upmo(ans, dp());
    /* rep(u,1,n+1){ */
    /* 	int d; */
    /* 	if(!bel[u])d=r-1-h[u];else d=r-h[u]; */
    /* 	if(bel[u]){ */
    /* 		to[u]=0; */
    /* 		boun[u]=d; */
    /* 	}else{ */
    /* 		to[u]=0; */
    /* 		boun[u]=d+1; */
    /* 		if(d==0){ */
    /* 			to[u]=1; */
    /* 			boun[u]=0; */
    /* 		} */
    /* 	} */
    /* } */
    /* upmo(ans,-dp()); */

    /* rep(u,1,n+1){ */
    /* 	int d; */
    /* 	if(!bel[u])d=r-1-h[u];else d=r-h[u]; */
    /* 	if(bel[u]){ */
    /* 		to[u]=0; */
    /* 		boun[u]=d; */
    /* 	}else{ */
    /* 		to[u]=0; */
    /* 		boun[u]=d+1; */
    /* 		if(d==0){ */
    /* 			to[u]=-1; */
    /* 			boun[u]=0; */
    /* 		} */
    /* 	} */
    /* } */
    /* upmo(ans,-dp()); */

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d + 1;
      } else {
        to[u] = 0;
        boun[u] = d;
      }
    }
    upmo(ans, dp());

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (!bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = 1;
          boun[u] = 0;
        }
      }
    }
    // upmo(ans,-dp());

    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (!bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 0;
        boun[u] = d + 1;
        if (d == 0) {
          to[u] = -1;
          boun[u] = 0;
        }
      }
    }
    // upmo(ans,-dp());
    /* rep(u,1,n+1){ */
    /* 	int d; */
    /* 	if(!bel[u])d=r-1-h[u];else d=r-h[u]; */
    /* 	if(!bel[u]){ */
    /* 		to[u]=1; */
    /* 		boun[u]=d+1; */
    /* 		if(d==0){ */
    /* 			to[u]=0; */
    /* 			boun[u]=0; */
    /* 		} */
    /* 	}else{ */
    /* 		to[u]=0; */
    /* 		boun[u]=d+1; */
    /* 		if(d==0){ */
    /* 			to[u]=1; */
    /* 			boun[u]=0; */
    /* 		} */
    /* 	} */
    /* } */
    /* upmo(ans,dp()); */
    /* rep(u,1,n+1){ */
    /* 	int d; */
    /* 	if(!bel[u])d=r-1-h[u];else d=r-h[u]; */
    /* 	if(bel[u]){ */
    /* 		to[u]=1; */
    /* 		boun[u]=d+1; */
    /* 		if(d==0){ */
    /* 			to[u]=0; */
    /* 			boun[u]=0; */
    /* 		} */
    /* 	}else{ */
    /* 		to[u]=0; */
    /* 		boun[u]=d+1; */
    /* 		if(d==0){ */
    /* 			to[u]=1; */
    /* 			boun[u]=0; */
    /* 		} */
    /* 	} */
    /* } */
    /* upmo(ans,dp()); */
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (!bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 1;
        boun[u] = d;
      }
    }
    upmo(ans, -dp());
    rep(u, 1, n + 1) {
      int d;
      if (!bel[u])
        d = r - 1 - h[u];
      else
        d = r - h[u];
      if (bel[u]) {
        to[u] = 0;
        boun[u] = d;
      } else {
        to[u] = 1;
        boun[u] = d;
      }
    }
    upmo(ans, -dp());
  }

  printf("%d\\n", ans);
#ifdef JCVB
  debug("time: %d\\n", int(clock() - _time_jc));
#endif
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define pii pair<int, int>
#define fi first
#define se second
#define mp make_pair
#define poly vector<ll>
#define For(i, l, r) for (int i = (int)(l); i <= (int)(r); i++)
#define Rep(i, r, l) for (int i = (int)(r); i >= (int)(l); i--)
#define pb push_back
inline char gc() {
  static char buf[100000], *p1 = buf, *p2 = buf;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
#define gc getchar
inline ll read() {
  ll x = 0;
  char ch = gc();
  bool positive = 1;
  for (; !isdigit(ch); ch = gc())
    if (ch == '-')
      positive = 0;
  for (; isdigit(ch); ch = gc())
    x = x * 10 + ch - '0';
  return positive ? x : -x;
}
inline void write(ll x) {
  if (x < 0) {
    x = -x;
    putchar('-');
  }
  if (x >= 10)
    write(x / 10);
  putchar('0' + x % 10);
}
inline void writeln(ll x) {
  write(x);
  puts("");
}
inline void writep(ll x) {
  write(x);
  putchar(' ');
}
inline ull rnd() { return ((ull)rand() << 30 ^ rand()) << 4 | rand() % 4; }
const int N = 1005, mo = 1e9 + 7;
int dep[N], fa[N], D;
poly v[N];
void dfs(int u) {
  dep[u] = dep[fa[u]] + 1;
  for (auto k : v[u]) {
    if (k == fa[u])
      continue;
    fa[k] = u;
    dfs(k);
  }
}
int f[N][N << 1];
void dfs(int u, int fa, int D, int dep, int t) {
  int l = dep - D + t, r = D - dep + t;
  For(i, l + 505, r + 505) f[u][i] = 1;
  for (auto k : v[u]) {
    if (k == fa)
      continue;
    dfs(k, u, D, dep + 1, t);
    For(i, l + 505, r + 505) {
      int ssw = (f[k][i - 1] + f[k][i + 1]) % mo;
      f[u][i] = (ll)f[u][i] * ssw % mo;
    }
  }
}
int solve1(int u) {
  dfs(u, 0, D, 0, 1);
  int res = 0;
  For(i, 0, 1000) res = (res + f[u][i]) % mo;
  return res;
}
int solve2(int u, int v, int t) {
  memset(f, 0, sizeof(f));
  dfs(u, v, D + (!t), 0, 0);
  dfs(v, u, D, 0, t);
  int res = 0;
  For(i, 1, 1000) {
    int ssw = (f[v][i - 1] + f[v][i + 1]) % mo;
    res = (res + (ll)f[u][i] * ssw) % mo;
  }
  return res;
}
int main() {
  int n = read();
  read();
  For(i, 1, n - 1) {
    int x = read(), y = read();
    v[x].pb(y);
    v[y].pb(x);
  }
  dep[0] = -1;
  int rt = 0;
  dfs(1);
  For(i, 1, n) if (dep[i] > dep[rt]) rt = i;
  memset(fa, 0, sizeof(fa));
  dfs(rt);
  For(i, rt = 1, n) if (dep[i] > dep[rt]) rt = i;
  if (dep[rt] % 2 == 0) {
    D = dep[rt] / 2;
    For(i, 1, D) rt = fa[rt];
    cout << solve1(rt);
  } else {
    D = dep[rt] / 2;
    For(i, 1, D) rt = fa[rt];
    int u = rt, v = fa[rt];
    int res = (solve2(u, v, 0) + solve2(v, u, 0)) % mo;
    int ssw = (solve2(u, v, 1) + solve2(u, v, -1)) % mo;
    res = (res - ssw + mo) % mo;
    cout << res;
  }
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define pii pair<int, int>
#define fi first
#define se second
#define mp make_pair
#define poly vector<ll>
#define For(i, l, r) for (int i = (int)(l); i <= (int)(r); i++)
#define Rep(i, r, l) for (int i = (int)(r); i >= (int)(l); i--)
#define pb push_back
inline char gc() {
  static char buf[100000], *p1 = buf, *p2 = buf;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
#define gc getchar
inline ll read() {
  ll x = 0;
  char ch = gc();
  bool positive = 1;
  for (; !isdigit(ch); ch = gc())
    if (ch == '-')
      positive = 0;
  for (; isdigit(ch); ch = gc())
    x = x * 10 + ch - '0';
  return positive ? x : -x;
}
inline void write(ll x) {
  if (x < 0) {
    x = -x;
    putchar('-');
  }
  if (x >= 10)
    write(x / 10);
  putchar('0' + x % 10);
}
inline void writeln(ll x) {
  write(x);
  puts("");
}
inline void writep(ll x) {
  write(x);
  putchar(' ');
}
inline ull rnd() { return ((ull)rand() << 30 ^ rand()) << 4 | rand() % 4; }
const int N = 2005, mo = 1e9 + 7;
int dep[N], fa[N], D;
poly v[N];
void dfs(int u) {
  dep[u] = dep[fa[u]] + 1;
  for (auto k : v[u]) {
    if (k == fa[u])
      continue;
    fa[k] = u;
    dfs(k);
  }
}
int f[N][N << 1];
void dfs(int u, int fa, int D, int dep, int t) {
  int l = dep - D + t, r = D - dep + t;
  For(i, l + 505, r + 505) f[u][i] = 1;
  for (auto k : v[u]) {
    if (k == fa)
      continue;
    dfs(k, u, D, dep + 1, t);
    For(i, l + 505, r + 505) {
      int ssw = (f[k][i - 1] + f[k][i + 1]) % mo;
      f[u][i] = (ll)f[u][i] * ssw % mo;
    }
  }
}
int solve1(int u) {
  dfs(u, 0, D, 0, 1);
  int res = 0;
  For(i, 0, 1005) res = (res + f[u][i]) % mo;
  return res;
}
int solve2(int u, int v, int t) {
  memset(f, 0, sizeof(f));
  dfs(u, v, D + (!t), 0, 0);
  dfs(v, u, D, 0, t);
  int res = 0;
  For(i, 1, 1005) {
    int ssw = (f[v][i - 1] + f[v][i + 1]) % mo;
    res = (res + (ll)f[u][i] * ssw) % mo;
  }
  return res;
}
int main() {
  int n = read();
  For(i, 1, n - 1) {
    int x = read(), y = read();
    v[x].pb(y);
    v[y].pb(x);
  }
  dep[0] = -1;
  int rt = 0;
  dfs(1);
  For(i, 1, n) if (dep[i] > dep[rt]) rt = i;
  memset(fa, 0, sizeof(fa));
  dfs(rt);
  For(i, rt = 1, n) if (dep[i] > dep[rt]) rt = i;
  if (dep[rt] % 2 == 0) {
    D = dep[rt] / 2;
    For(i, 1, D) rt = fa[rt];
    cout << solve1(rt);
  } else {
    D = dep[rt] / 2;
    For(i, 1, D) rt = fa[rt];
    int u = rt, v = fa[rt];
    int res = (solve2(u, v, 0) + solve2(v, u, 0)) % mo;
    int ssw = (solve2(u, v, 1) + solve2(u, v, -1)) % mo;
    res = (res - ssw + mo) % mo;
    cout << res;
  }
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x, to) for (x = 0; x < (to); x++)
#define FORR(x, arr) for (auto &x : arr)
#define ITR(x, c) for (__typeof(c.begin()) x = c.begin(); x != c.end(); x++)
#define ALL(a) (a.begin()), (a.end())
#define ZERO(a) memset(a, 0, sizeof(a))
#define MINUS(a) memset(a, 0xff, sizeof(a))
//-------------------------------------------------------

int N;
vector<vector<int>> E;
vector<int> D;
ll dp[1010][1010];
ll mo = 1000000007;

pair<int, int> farthest(vector<vector<int>> &E, int cur, int pre, int d,
                        vector<int> &D) {
  D[cur] = d;
  pair<int, int> r = {d, cur};
  FORR(e, E[cur]) if (e != pre) r = max(r, farthest(E, e, cur, d + 1, D));
  return r;
}

pair<int, vector<int>> diameter(vector<vector<int>> &E) { // diameter,center
  vector<int> D[2];
  D[0].resize(E.size());
  D[1].resize(E.size());
  auto v1 = farthest(E, 0, 0, 0, D[0]);
  auto v2 = farthest(E, v1.second, v1.second, 0, D[0]);
  farthest(E, v2.second, v2.second, 0, D[1]);
  pair<int, vector<int>> R;
  R.first = v2.first;
  for (int i = E.size() - 1; i >= 0; i--)
    if (D[0][i] + D[1][i] == R.first && abs(D[0][i] - D[1][i]) <= 1)
      R.second.push_back(i);
  return R;
}

void dfs(int cur, int pre, int d, int md, int p1, int p2) {
  if (d == md) {
    dp[cur][505] = 1;
  } else {
    FORR(e, E[cur]) if (e != pre) dfs(e, cur, d + 1, md, p1, p2);
    for (int x = -503; x <= 503; x++)
      if (abs(x + p2) <= md - d + p1) {
        dp[cur][505 + x] = 1;
        FORR(e, E[cur])
        if (e != pre)(dp[cur][505 + x] *=
                      (dp[e][505 + x + 1] + dp[e][505 + x - 1])) %= mo;
      }
  }
}

void solve() {
  int i, j, k, l, r, x, y;
  string s;

  cin >> N;
  E.resize(N);
  FOR(i, N - 1) {
    cin >> x >> y;
    E[x - 1].push_back(y - 1);
    E[y - 1].push_back(x - 1);
  }

  auto dia = diameter(E);
  if (dia.first % 2 == 0) {
    dfs(dia.second[0], -1, 0, dia.first / 2, 0, 0);
    cout << accumulate(dp[dia.second[0]], dp[dia.second[0]] + 1010, 0LL) % mo
         << endl;
  } else {
    assert(0);
    /*
    dfs(dia.second[0],dia.second[1],0,dia.first/2,0,1);
    dfs(dia.second[1],dia.second[0],1,dia.first/2,0,0);
    */
  }
}

int main(int argc, char **argv) {
  string s;
  int i;
  if (argc == 1)
    ios::sync_with_stdio(false), cin.tie(0);
  FOR(i, argc - 1) s += argv[i + 1], s += '\\n';
  FOR(i, s.size()) ungetc(s[s.size() - 1 - i], stdin);
  solve();
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x, to) for (x = 0; x < (to); x++)
#define FORR(x, arr) for (auto &x : arr)
#define ITR(x, c) for (__typeof(c.begin()) x = c.begin(); x != c.end(); x++)
#define ALL(a) (a.begin()), (a.end())
#define ZERO(a) memset(a, 0, sizeof(a))
#define MINUS(a) memset(a, 0xff, sizeof(a))
//-------------------------------------------------------

int N;
vector<vector<int>> E;
vector<int> D;
ll dp[1020][1020];
ll mo = 1000000007;

pair<int, int> farthest(vector<vector<int>> &E, int cur, int pre, int d,
                        vector<int> &D) {
  D[cur] = d;
  pair<int, int> r = {d, cur};
  FORR(e, E[cur]) if (e != pre) r = max(r, farthest(E, e, cur, d + 1, D));
  return r;
}

pair<int, vector<int>> diameter(vector<vector<int>> &E) { // diameter,center
  vector<int> D[2];
  D[0].resize(E.size());
  D[1].resize(E.size());
  auto v1 = farthest(E, 0, 0, 0, D[0]);
  auto v2 = farthest(E, v1.second, v1.second, 0, D[0]);
  farthest(E, v2.second, v2.second, 0, D[1]);
  pair<int, vector<int>> R;
  R.first = v2.first;
  for (int i = E.size() - 1; i >= 0; i--)
    if (D[0][i] + D[1][i] == R.first && abs(D[0][i] - D[1][i]) <= 1)
      R.second.push_back(i);
  return R;
}

void dfs(int cur, int pre, int d, int md, int p) {
  FORR(e, E[cur]) if (e != pre) dfs(e, cur, d + 1, md, p);
  for (int x = -503; x <= 503; x++)
    if ((abs(x + p) <= md - d) && (abs(x - p) <= md - d)) {
      dp[cur][505 + x] = 1;
      FORR(e, E[cur])
      if (e != pre)(dp[cur][505 + x] *=
                    (dp[e][505 + x + 1] + dp[e][505 + x - 1])) %= mo;
    }
}

void solve() {
  int i, j, k, l, r, x, y;
  string s;

  cin >> N;
  E.resize(N);
  FOR(i, N - 1) {
    cin >> x >> y;
    E[x - 1].push_back(y - 1);
    E[y - 1].push_back(x - 1);
  }

  auto dia = diameter(E);
  if (dia.first % 2 == 0) {
    dfs(dia.second[0], -1, 0, dia.first / 2, 0);
    cout << accumulate(dp[dia.second[0]], dp[dia.second[0]] + 1010, 0LL) % mo
         << endl;
  } else {
    ll ret = 0;
    dfs(dia.second[0], dia.second[1], 0, dia.first / 2, 0);
    dfs(dia.second[1], dia.second[0], 0, dia.first / 2 + 1, 0);
    for (x = 3; x <= 1008; x++)
      (ret += dp[dia.second[0]][x] *
              (dp[dia.second[1]][x + 1] + dp[dia.second[1]][x - 1])) %= mo;

    ZERO(dp);
    dfs(dia.second[0], dia.second[1], 0, dia.first / 2 + 1, 0);
    dfs(dia.second[1], dia.second[0], 0, dia.first / 2, 0);
    for (x = 3; x <= 1008; x++)
      (ret += dp[dia.second[0]][x] *
              (dp[dia.second[1]][x + 1] + dp[dia.second[1]][x - 1])) %= mo;

    ZERO(dp);
    dfs(dia.second[0], dia.second[1], 0, dia.first / 2, 0);
    dfs(dia.second[1], dia.second[0], 0, dia.first / 2, 0);
    for (i = 3; i <= 1008; i++)
      ret -= 2 * dp[dia.second[0]][i] * dp[dia.second[1]][i] % mo;
    for (i = 3; i <= 1008; i++)
      ret -= dp[dia.second[0]][i] * dp[dia.second[1]][i + 2] % mo;
    for (i = 3; i <= 1008; i++)
      ret -= dp[dia.second[0]][i] * dp[dia.second[1]][i - 2] % mo;
    cout << (ret % mo + mo) % mo << endl;
  }
}

int main(int argc, char **argv) {
  string s;
  int i;
  if (argc == 1)
    ios::sync_with_stdio(false), cin.tie(0);
  FOR(i, argc - 1) s += argv[i + 1], s += '\\n';
  FOR(i, s.size()) ungetc(s[s.size() - 1 - i], stdin);
  solve();
  return 0;
}


#include <bits/stdc++.h>
#define syosu(x) fixed << setprecision(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<string> vs;
typedef vector<P> vp;
typedef vector<vp> vvp;
typedef vector<pll> vpll;
typedef pair<int, P> pip;
typedef vector<pip> vip;
const int inf = 1 << 30;
const ll INF = 1ll << 60;
const double pi = acos(-1);
const double eps = 1e-9;
const ll mod = 1e9 + 7;
const int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};

int n, N = 0, M;
vvi g;
vi a, b;
vector<vvl> dp;

P dfs(int v, int d, int w) {
  P p = {d, v};
  for (auto u : g[v])
    if (u != w)
      p = max(p, dfs(u, d + 1, v));
  return p;
}

bool DFS(int v, int w, int p) {
  bool B = 0;
  if (v == w)
    B = 1;
  for (auto u : g[v])
    if (u != p) {
      B |= DFS(u, w, v);
    }
  if (B) {
    a.push_back(v);
    b[v]++;
    N++;
  }
  return B;
}

int Rec(int v, int p) {
  int D = 1, B = 0;
  vvl DP;
  for (auto u : g[v])
    if (u != p) {
      int d = Rec(u, v), D_ = D;
      D = max(D, d + 1);
      vvl DP_(D, vl(D));
      if (!B) {
        for (int i = 0; i < d; i++)
          for (int j = 0; j < d; j++) {
            (DP_[i + 1][j] += dp[u][i][j]) %= mod;
            (DP_[i][j + 1] += dp[u][i][j]) %= mod;
          }
        B = 1;
      } else {
        for (int i = 0; i < D_; i++)
          for (int j = 0; j < D_; j++)
            if (DP[i][j]) {
              for (int k = 0; k < min(d, M - j + 1); k++)
                for (int l = 0; l < min(d, M - i + 1); l++) {
                  if (j + k + 1 <= M)
                    (DP_[max(i, k + 1)][max(j, l)] += DP[i][j] * dp[u][k][l]) %=
                        mod;
                  if (i + l + 1 <= M)
                    (DP_[max(i, k)][max(j, l + 1)] += DP[i][j] * dp[u][k][l]) %=
                        mod;
                }
            }
      }
      DP = DP_;
    }
  if (D == 1) {
    DP = vvl(1, vl(1));
    DP[0][0]++;
  }
  dp[v] = DP;
  return D;
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n;
  b = vi(n);
  g = vvi(n);
  dp = vector<vvl>(n);
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  int L = dfs(0, 0, -1).second, R = dfs(L, 0, -1).second;
  DFS(L, R, -1);
  M = N / 2;
  ll C = a[N / 2], res = 0;
  Rec(C, -1);
  for (int i = 0; i <= M; i++)
    for (int j = 0; j <= M; j++)
      (res += dp[C][i][j]) %= mod;
  cout << res << endl;
}

#include <bits/stdc++.h>
#define syosu(x) fixed << setprecision(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<string> vs;
typedef vector<P> vp;
typedef vector<vp> vvp;
typedef vector<pll> vpll;
typedef pair<int, P> pip;
typedef vector<pip> vip;
const int inf = 1 << 30;
const ll INF = 1ll << 60;
const double pi = acos(-1);
const double eps = 1e-9;
const ll mod = 1e9 + 7;
const int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};

int n, N = 0, M;
vvi g;
vi a, b;
vector<vvl> dp;

P dfs(int v, int d, int w) {
  P p = {d, v};
  for (auto u : g[v])
    if (u != w)
      p = max(p, dfs(u, d + 1, v));
  return p;
}

bool DFS(int v, int w, int p) {
  bool B = 0;
  if (v == w)
    B = 1;
  for (auto u : g[v])
    if (u != p) {
      B |= DFS(u, w, v);
    }
  if (B) {
    a.push_back(v);
    b[v]++;
    N++;
  }
  return B;
}

int Rec(int v, int p) {
  int D = 1, B = 0;
  vvl DP;
  for (auto u : g[v])
    if (u != p) {
      int d = Rec(u, v), D_ = D;
      D = max(D, d + 1);
      vvl DP_(D, vl(D));
      if (!B) {
        for (int i = 0; i < d; i++)
          for (int j = 0; j < d; j++) {
            (DP_[i + 1][j] += dp[u][i][j]) %= mod;
            (DP_[i][j + 1] += dp[u][i][j]) %= mod;
          }
        B = 1;
      } else {
        for (int i = 0; i < D_; i++)
          for (int j = 0; j < D_; j++)
            if (DP[i][j]) {
              for (int k = 0; k < min(d, M - j + 1); k++)
                for (int l = 0; l < min(d, M - i + 1); l++) {
                  if (j + k + 1 <= M)
                    (DP_[max(i, k + 1)][max(j, l)] += DP[i][j] * dp[u][k][l]) %=
                        mod;
                  if (i + l + 1 <= M)
                    (DP_[max(i, k)][max(j, l + 1)] += DP[i][j] * dp[u][k][l]) %=
                        mod;
                }
            }
      }
      DP = DP_;
    }
  for (auto u : g[v])
    if (u != p)
      dp[u].clear();
  if (D == 1) {
    DP = vvl(1, vl(1));
    DP[0][0]++;
  }
  dp[v] = DP;
  return D;
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n;
  b = vi(n);
  g = vvi(n);
  dp = vector<vvl>(n);
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  int L = dfs(0, 0, -1).second, R = dfs(L, 0, -1).second;
  DFS(L, R, -1);
  M = N / 2;
  ll C = a[N / 2], res = 0;
  Rec(C, -1);
  for (int i = 0; i <= M; i++)
    for (int j = 0; j <= M; j++)
      (res += dp[C][i][j]) %= mod;
  cout << res << endl;
}


// In the Name of God
// Ya Ali

#include <bits/stdc++.h>

#define int long long

#define pb push_back

#define err(A) cout << #A << " = " << (A) << endl

using namespace std;

const int M = 1e9 + 7 + 0;
const int maxn = 1024;

int n;

vector<int> g[maxn];

int lvl[maxn];

int d0[maxn];
int d1[maxn];

int D, D1, D2;
int far;

int r0, r1;

int dp[maxn][maxn / 2];
int cp[maxn][maxn / 2];

int ans;

void pfs(int v, int par = n) {
  lvl[v] = lvl[par] + 1;
  for (int u : g[v])
    if (u != par)
      pfs(u, v);
  if (lvl[v] > lvl[far])
    far = v;
}

void dfs(int v, int par = n) {
  lvl[v] = lvl[par] + 1;
  for (int i = 0; i <= D2; i++) {
    if (D1 - lvl[v] >= i)
      dp[v][i] = 1;
    if (D1 - lvl[v] >= i - 1)
      cp[v][i] = 1;
  }
  for (int u : g[v])
    if (u != par) {
      dfs(u, v);
      for (int i = 0; i <= D2; i++) {
        (dp[v][i] *= dp[u][i] + (i ? dp[u][i - 1] : 0)) %= M;
        (cp[v][i] *= cp[u][i] + (i ? cp[u][i - 1] : 0)) %= M;
      }
    }
}

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

  cin >> n;
  for (int v, u, i = 0; i < n - 1; i++) {
    cin >> v >> u;
    v--, u--;
    g[v].pb(u);
    g[u].pb(v);
  }

  lvl[n] = -1;
  pfs(far);
  pfs(far);
  for (int i = 0; i < n; i++)
    d0[i] = lvl[i];
  pfs(far);
  for (int i = 0; i < n; i++)
    d1[i] = lvl[i];

  D = lvl[far];
  D1 = (D + 0) / 2;
  D2 = (D + 1) / 2;

  if (D & 1) {
    for (int i = 0; i < n; i++)
      if (d0[i] + d1[i] == D)
        if (d0[i] == d1[i] - 1)
          r0 = i;
        else if (d0[i] == d1[i] + 1)
          r1 = i;
    lvl[r1] = -1;
    dfs(r0, r1);
    lvl[r0] = -1;
    dfs(r1, r0);
    for (int i = 0; i <= D2; i++) {
      ans += dp[r0][i] * cp[r1][i] % M;
      ans += cp[r0][i + 1] * dp[r1][i] % M;
      ans -= dp[r0][i] * dp[r1][i] % M;
      ans += dp[r1][i] * cp[r0][i] % M;
      ans += cp[r1][i + 1] * dp[r0][i] % M;
      ans -= dp[r1][i] * dp[r0][i] % M;
      ans -= dp[r1][i] * dp[r0][i] % M;
      ans %= M;
      return 1;
    }
  } else {
    for (int i = 0; i < n; i++)
      if (d0[i] + d1[i] == D and d0[i] == d1[i])
        r0 = i;
    dfs(r0);
    for (int i = 0; i <= D2; i++)
      ans += dp[r0][i];
  }

  ans = (ans % M + M) % M;

  cout << ans << endl;

  return 0;
}

// In the Name of God
// Ya Ali

#include <bits/stdc++.h>

#define int long long

#define pb push_back

#define err(A) cout << #A << " = " << (A) << endl

using namespace std;

const int M = 1e9 + 7 + 0;
const int maxn = 1024;

int n;

vector<int> g[maxn];

int lvl[maxn];

int d0[maxn];
int d1[maxn];

int D, D1, D2;
int far;

int r0, r1;

int dp[maxn][maxn / 2];
int cp[maxn][maxn / 2];

int ans;

void pfs(int v, int par = n) {
  lvl[v] = lvl[par] + 1;
  for (int u : g[v])
    if (u != par)
      pfs(u, v);
  if (lvl[v] > lvl[far])
    far = v;
}

void dfs(int v, int par = n) {
  lvl[v] = lvl[par] + 1;
  for (int i = 0; i <= D2; i++) {
    if (D1 - lvl[v] >= i)
      dp[v][i] = 1;
    if (D1 - lvl[v] >= i - 1)
      cp[v][i] = 1;
  }
  for (int u : g[v])
    if (u != par) {
      dfs(u, v);
      for (int i = 0; i <= D2; i++) {
        (dp[v][i] *= dp[u][i] + (i ? dp[u][i - 1] : 0)) %= M;
        (cp[v][i] *= cp[u][i] + (i ? cp[u][i - 1] : 0)) %= M;
      }
    }
}

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

  cin >> n;
  for (int v, u, i = 0; i < n - 1; i++) {
    cin >> v >> u;
    v--, u--;
    g[v].pb(u);
    g[u].pb(v);
  }

  lvl[n] = -1;
  pfs(far);
  pfs(far);
  for (int i = 0; i < n; i++)
    d0[i] = lvl[i];
  pfs(far);
  for (int i = 0; i < n; i++)
    d1[i] = lvl[i];

  D = lvl[far];
  D1 = (D + 0) / 2;
  D2 = (D + 1) / 2;

  if (D & 1) {
    for (int i = 0; i < n; i++)
      if (d0[i] + d1[i] == D)
        if (d0[i] == d1[i] - 1)
          r0 = i;
        else if (d0[i] == d1[i] + 1)
          r1 = i;
    lvl[r1] = -1;
    dfs(r0, r1);
    lvl[r0] = -1;
    dfs(r1, r0);
    for (int i = 0; i <= D2; i++) {
      ans += dp[r0][i] * cp[r1][i] % M;
      ans += cp[r0][i + 1] * dp[r1][i] % M;
      ans -= dp[r0][i] * dp[r1][i] % M;
      ans -= dp[r0][i + 1] * dp[r1][i] % M;
      ans += dp[r1][i] * cp[r0][i] % M;
      ans += cp[r1][i + 1] * dp[r0][i] % M;
      ans -= dp[r1][i] * dp[r0][i] % M;
      ans -= dp[r1][i + 1] * dp[r0][i] % M;
      ans %= M;
    }
  } else {
    for (int i = 0; i < n; i++)
      if (d0[i] + d1[i] == D and d0[i] == d1[i])
        r0 = i;
    dfs(r0);
    for (int i = 0; i <= D2; i++)
      ans += dp[r0][i];
  }

  ans = (ans % M + M) % M;

  cout << ans << endl;

  return 0;
}


#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

mt19937 mrand(random_device{}());

int rnd(int x) { return mrand() % x; }

typedef long double ld;
typedef long long ll;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define pb push_back
#define mp make_pair
#define sz(x) ((int)(x).size())
#define TASK "text"

const int inf = (int)1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld)-1.0);

const int mod = (int)1e9 + 7;

void add(int &x, int y) {
  if ((x += y) >= mod) {
    x -= mod;
  }
}

int mult(int x, int y) { return (long long)x * y % mod; }

int myPower(int x, int pw) {
  int res = 1;
  for (; pw; pw >>= 1) {
    if (pw & 1) {
      res = mult(res, x);
    }
    x = mult(x, x);
  }
  return res;
}

void precalc() {}

const int maxn = (int)1e3 + 10;
int n;

vector<vector<int>> es;

int read() {
  if (scanf("%d", &n) < 1) {
    return 0;
  }
  es = vector<vector<int>>(n);
  for (int i = 0; i < n - 1; ++i) {
    int s, t;
    scanf("%d%d", &s, &t);
    --s, --t;
    es[s].pb(t), es[t].pb(s);
  }
  return 1;
}

int dist[maxn];
int dist1[maxn];

void dfs1(int v, int p) {
  for (int u : es[v]) {
    if (u == p) {
      continue;
    }
    dist[u] = dist[v] + 1;
    dfs1(u, v);
  }
}

int used[maxn];

typedef vector<vector<int>> vvi;

int cnt[maxn];

void dfs2(int v, int p) {
  cnt[v] = 1;
  for (int u : es[v]) {
    if (u == p || used[u]) {
      continue;
    }
    dfs2(u, v);
    cnt[v] += cnt[u];
  }
}

int diam, D;

void adde(vvi &a) {
  int n = sz(a);
  for (int i = 0; i < n; ++i) {
    a[i].pb(0);
  }
  a.pb(vector<int>(n + 1, 0));

  for (int i = n - 1; i >= 0; --i) {
    for (int j = n - 1; j >= 0; --j) {
      int x = a[i][j];
      if (!x) {
        continue;
      }
      a[i][j] = 0;
      if (i + 1 <= D) {
        add(a[i + 1][j], x);
      }
      if (i + 1 <= D) {
        add(a[i][j + 1], x);
      }
    }
  }
}

void makesum(vvi &a) {
  for (int i = 0; i < sz(a); ++i) {
    for (int j = 0; j < sz(a); ++j) {
      int &res = a[i][j];
      if (i) {
        add(res, a[i - 1][j]);
        if (j) {
          add(res, mod - a[i - 1][j - 1]);
        }
      }
      if (j) {
        add(res, a[i][j - 1]);
      }
    }
  }
}

void makeone(vvi &a) {
  for (int i = sz(a) - 1; i >= 0; --i) {
    for (int j = sz(a) - 1; j >= 0; --j) {
      int &res = a[i][j];
      if (i) {
        add(res, mod - a[i - 1][j]);
        if (j) {
          add(res, a[i - 1][j - 1]);
        }
      }
      if (j) {
        add(res, mod - a[i][j - 1]);
      }
    }
  }
}

void update(vvi &a, vvi &b) {
  /*eprintf("update:\\n");
  eprintf("%d\\n", sz(a));
  for (int i = 0; i < sz(a); ++i) {
    for (int j = 0; j < sz(a); ++j) {
      eprintf("%d%c", a[i][j], " \\n"[j == sz(a) - 1]);
    }
  }
  eprintf("%d\\n", sz(b));
  for (int i = 0; i < sz(b); ++i) {
    for (int j = 0; j < sz(b); ++j) {
      eprintf("%d%c", b[i][j], " \\n"[j == sz(b) - 1]);
    }
  }*/
  assert(sz(a) >= sz(b));

  makesum(a);
  makesum(b);
  for (int i = 0; i < sz(a); ++i) {
    for (int j = 0; j < sz(a); ++j) {
      a[i][j] = mult(a[i][j], b[min(sz(b) - 1, i)][min(sz(b) - 1, j)]);
    }
  }
  makeone(a);
}

vvi *dfs3(int v, int p) {
  int u0 = -1;
  for (int u : es[v]) {
    if (u == p || used[u]) {
      continue;
    }
    if (u0 == -1 || cnt[u] > cnt[u0]) {
      u0 = u;
    }
  }
  if (u0 == -1) {
    return new vvi({{1}});
  }
  auto ans = dfs3(u0, v);
  adde(*ans);

  for (int u : es[v]) {
    if (u == p || u == u0 || used[u]) {
      continue;
    }
    auto got = dfs3(u, v);
    adde(*got);
    update(*ans, *got);
  }
  return ans;
}

int ans[maxn];
int adds[maxn];

void solve() {
  dist[0] = 0;
  dfs1(0, -1);
  int v = max_element(dist, dist + n) - dist;

  dist[v] = 0;
  dfs1(v, -1);
  int u = max_element(dist, dist + n) - dist;
  diam = dist[u];

  memcpy(dist1, dist, sizeof(dist[0]) * n);

  dist[u] = 0;
  dfs1(u, -1);

  D = (diam + 1) / 2;
  // eprintf("diam = %d\\n", diam);

  for (int i = 0; i < n; ++i) {
    used[i] = 0;
  }
  int vs[2];
  int k = 0;
  for (int i = 0; i < n; ++i) {
    if (dist[i] + dist1[i] == diam && abs(dist[i] - dist1[i]) <= 1) {
      vs[k++] = i;
      used[i] = 1;
    }
  }
  assert(1 <= k && k <= 2);
  for (int i = 0; i < k; ++i) {
    dfs2(i, -1);
  }

  // eprintf("middle %d\\n", vs[0]);

  int res = 0;
  if (k == 1) {
    dfs2(vs[0], -1);
    for (int i = 0; i <= D; ++i) {
      ans[i] = 1;
    }
    for (int u : es[vs[0]]) {
      auto &got = *dfs3(u, vs[0]);
      adde(got);
      for (int i = 0; i <= D; ++i) {
        adds[i] = 0;
      }
      for (int i = 0; i < sz(got); ++i) {
        for (int j = 0; j < sz(got); ++j) {
          int cur = got[i][j];
          if (!cur) {
            continue;
          }
          // eprintf("u = %d, (%d,%d) x%d\\n", u, i, j, cur);
          int l = i, r = D - j;
          if (l <= r) {
            // eprintf("[%d..%d]\\n", l, r);
            add(adds[l], cur);
            add(adds[r + 1], mod - cur);
          }
        }
      }
      int bal = 0;
      for (int i = 0; i <= D; ++i) {
        add(bal, adds[i]);
        ans[i] = mult(ans[i], bal);
      }
    }
    for (int i = 0; i <= D; ++i) {
      add(res, ans[i]);
    }
  } else {
    auto &ans1 = *(dfs3(vs[0], -1));
    auto &ans2 = *(dfs3(vs[1], -1));
    assert(sz(ans1) == D && sz(ans2) == sz(ans1));
    // eprintf("D = %d\\n", D);
    for (int i = 0; i < sz(ans1); ++i) {
      add(res, mult(2, mult(ans1[i][D - 1 - i], ans2[i][D - 1 - i])));
      if (i) {
        add(res, mult(ans1[i][D - 1 - i], ans2[i][D - i]));
        add(res, mult(ans2[i][D - 1 - i], ans1[i][D - i]));

        add(res, mult(ans1[i][D - 1 - i], ans2[i - 1][D - i]));
        add(res, mult(ans2[i][D - 1 - i], ans1[i - 1][D - i]));
      }
      if (i < sz(ans1) - 1) {
        add(res, mult(ans1[i][D - 1 - i], ans2[i + 1][D - 1 - i]));
        add(res, mult(ans2[i][D - 1 - i], ans1[i + 1][D - 1 - i]));
      }
    }
  }

  printf("%d\\n", res);
  // exit(0);
}

int main() {
  precalc();
#ifdef LOCAL
  freopen(TASK ".out", "w", stdout);
  assert(freopen(TASK ".in", "r", stdin));
#endif

  while (1) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

mt19937 mrand(random_device{}());

int rnd(int x) { return mrand() % x; }

typedef long double ld;
typedef long long ll;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define pb push_back
#define mp make_pair
#define sz(x) ((int)(x).size())
#define TASK "text"

const int inf = (int)1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld)-1.0);

const int mod = (int)1e9 + 7;

void add(int &x, int y) {
  if ((x += y) >= mod) {
    x -= mod;
  }
}

int mult(int x, int y) { return (long long)x * y % mod; }

int myPower(int x, int pw) {
  int res = 1;
  for (; pw; pw >>= 1) {
    if (pw & 1) {
      res = mult(res, x);
    }
    x = mult(x, x);
  }
  return res;
}

void precalc() {}

const int maxn = (int)1e3 + 10;
int n;

vector<vector<int>> es;

int read() {
  if (scanf("%d", &n) < 1) {
    return 0;
  }
  es = vector<vector<int>>(n);
  for (int i = 0; i < n - 1; ++i) {
    int s, t;
    scanf("%d%d", &s, &t);
    --s, --t;
    es[s].pb(t), es[t].pb(s);
  }
  return 1;
}

int dist[maxn];
int dist1[maxn];

void dfs1(int v, int p) {
  for (int u : es[v]) {
    if (u == p) {
      continue;
    }
    dist[u] = dist[v] + 1;
    dfs1(u, v);
  }
}

int used[maxn];

typedef vector<vector<int>> vvi;

int cnt[maxn];

void dfs2(int v, int p) {
  cnt[v] = 1;
  for (int u : es[v]) {
    if (u == p || used[u]) {
      continue;
    }
    dfs2(u, v);
    cnt[v] += cnt[u];
  }
}

int diam, D;

void adde(vvi &a) {
  int n = sz(a);
  for (int i = 0; i < n; ++i) {
    a[i].pb(0);
  }
  a.pb(vector<int>(n + 1, 0));

  for (int i = n - 1; i >= 0; --i) {
    for (int j = n - 1; j >= 0; --j) {
      int x = a[i][j];
      if (!x) {
        continue;
      }
      a[i][j] = 0;
      if (i + 1 <= D) {
        add(a[i + 1][j], x);
      }
      if (i + 1 <= D) {
        add(a[i][j + 1], x);
      }
    }
  }
}

void makesum(vvi &a) {
  for (int i = 0; i < sz(a); ++i) {
    for (int j = 0; j < sz(a); ++j) {
      int &res = a[i][j];
      if (i) {
        add(res, a[i - 1][j]);
        if (j) {
          add(res, mod - a[i - 1][j - 1]);
        }
      }
      if (j) {
        add(res, a[i][j - 1]);
      }
    }
  }
}

void makeone(vvi &a) {
  for (int i = sz(a) - 1; i >= 0; --i) {
    for (int j = sz(a) - 1; j >= 0; --j) {
      int &res = a[i][j];
      if (i) {
        add(res, mod - a[i - 1][j]);
        if (j) {
          add(res, a[i - 1][j - 1]);
        }
      }
      if (j) {
        add(res, mod - a[i][j - 1]);
      }
    }
  }
}

void update(vvi &a, vvi &b) {
  /*eprintf("update:\\n");
  eprintf("%d\\n", sz(a));
  for (int i = 0; i < sz(a); ++i) {
    for (int j = 0; j < sz(a); ++j) {
      eprintf("%d%c", a[i][j], " \\n"[j == sz(a) - 1]);
    }
  }
  eprintf("%d\\n", sz(b));
  for (int i = 0; i < sz(b); ++i) {
    for (int j = 0; j < sz(b); ++j) {
      eprintf("%d%c", b[i][j], " \\n"[j == sz(b) - 1]);
    }
  }*/
  assert(sz(a) >= sz(b));

  makesum(a);
  makesum(b);
  for (int i = 0; i < sz(a); ++i) {
    for (int j = 0; j < sz(a); ++j) {
      a[i][j] = mult(a[i][j], b[min(sz(b) - 1, i)][min(sz(b) - 1, j)]);
    }
  }
  makeone(a);
}

vvi *dfs3(int v, int p) {
  int u0 = -1;
  for (int u : es[v]) {
    if (u == p || used[u]) {
      continue;
    }
    if (u0 == -1 || cnt[u] > cnt[u0]) {
      u0 = u;
    }
  }
  if (u0 == -1) {
    return new vvi({{1}});
  }
  auto ans = dfs3(u0, v);
  adde(*ans);

  for (int u : es[v]) {
    if (u == p || u == u0 || used[u]) {
      continue;
    }
    auto got = dfs3(u, v);
    adde(*got);
    if (sz(*ans) < sz(*got)) {
      swap(ans, got);
    }
    update(*ans, *got);
  }
  return ans;
}

int ans[maxn];
int adds[maxn];

void solve() {
  dist[0] = 0;
  dfs1(0, -1);
  int v = max_element(dist, dist + n) - dist;

  dist[v] = 0;
  dfs1(v, -1);
  int u = max_element(dist, dist + n) - dist;
  diam = dist[u];

  memcpy(dist1, dist, sizeof(dist[0]) * n);

  dist[u] = 0;
  dfs1(u, -1);

  D = (diam + 1) / 2;
  // eprintf("diam = %d\\n", diam);

  for (int i = 0; i < n; ++i) {
    used[i] = 0;
  }
  int vs[2];
  int k = 0;
  for (int i = 0; i < n; ++i) {
    if (dist[i] + dist1[i] == diam && abs(dist[i] - dist1[i]) <= 1) {
      vs[k++] = i;
      used[i] = 1;
    }
  }
  assert(1 <= k && k <= 2);
  for (int i = 0; i < k; ++i) {
    dfs2(i, -1);
  }

  // eprintf("middle %d\\n", vs[0]);

  int res = 0;
  if (k == 1) {
    dfs2(vs[0], -1);
    for (int i = 0; i <= D; ++i) {
      ans[i] = 1;
    }
    for (int u : es[vs[0]]) {
      auto &got = *dfs3(u, vs[0]);
      adde(got);
      for (int i = 0; i <= D; ++i) {
        adds[i] = 0;
      }
      for (int i = 0; i < sz(got); ++i) {
        for (int j = 0; j < sz(got); ++j) {
          int cur = got[i][j];
          if (!cur) {
            continue;
          }
          // eprintf("u = %d, (%d,%d) x%d\\n", u, i, j, cur);
          int l = i, r = D - j;
          if (l <= r) {
            // eprintf("[%d..%d]\\n", l, r);
            add(adds[l], cur);
            add(adds[r + 1], mod - cur);
          }
        }
      }
      int bal = 0;
      for (int i = 0; i <= D; ++i) {
        add(bal, adds[i]);
        ans[i] = mult(ans[i], bal);
      }
    }
    for (int i = 0; i <= D; ++i) {
      add(res, ans[i]);
    }
  } else {
    auto &ans1 = *(dfs3(vs[0], -1));
    auto &ans2 = *(dfs3(vs[1], -1));
    assert(sz(ans1) == D && sz(ans2) == sz(ans1));
    // eprintf("D = %d\\n", D);
    for (int i = 0; i < sz(ans1); ++i) {
      add(res, mult(2, mult(ans1[i][D - 1 - i], ans2[i][D - 1 - i])));
      if (i) {
        add(res, mult(ans1[i][D - 1 - i], ans2[i][D - i]));
        add(res, mult(ans2[i][D - 1 - i], ans1[i][D - i]));

        add(res, mult(ans1[i][D - 1 - i], ans2[i - 1][D - i]));
        add(res, mult(ans2[i][D - 1 - i], ans1[i - 1][D - i]));
      }
      if (i < sz(ans1) - 1) {
        add(res, mult(ans1[i][D - 1 - i], ans2[i + 1][D - 1 - i]));
        add(res, mult(ans2[i][D - 1 - i], ans1[i + 1][D - 1 - i]));
      }
    }
  }

  printf("%d\\n", res);
  // exit(0);
}

int main() {
  precalc();
#ifdef LOCAL
  freopen(TASK ".out", "w", stdout);
  assert(freopen(TASK ".in", "r", stdin));
#endif

  while (1) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#define ls (t << 1)
#define rs ((t << 1) + 1)
#define mid ((l + r) >> 1)
#define fi first
#define se second
#define mk make_pair
#define pb push_back

#define N 1005
#define M 200005
#define seed 23333
#define Mo 1000000007

using namespace std;
int i, j, m, n, p, k, f[N][N * 2], dis[N], fa[N], Q[N], x, y, dia[N], ans, D,
    col[N], Dis[N], lim[N];
vector<int> v[N];
void jia(int &x, int y) {
  x += y;
  if (x >= Mo)
    x -= Mo;
}
void jian(int &x, int y) {
  x -= y;
  if (x < 0)
    x += Mo;
}
int bfs(int *dis, int x) {
  memset(fa, 0, sizeof(fa));
  for (i = 1; i <= n; ++i)
    dis[i] = -1;
  dis[x] = 0;
  Q[Q[0] = 1] = x;
  int i, l;
  for (l = 1; l <= Q[0]; ++l) {
    int p = Q[l];
    for (i = 0; i < (int)v[p].size(); ++i) {
      int k = v[p][i];
      if (dis[k] != -1)
        continue;
      dis[k] = dis[p] + 1;
      fa[k] = p;
      Q[++Q[0]] = k;
    }
  }
  int now = 1;
  for (i = 1; i <= n; ++i)
    if (dis[now] < dis[i])
      now = i;
  return now;
}
void dfs(int x) {
  int i, j;
  for (i = -n + N; i <= n + N; ++i)
    if (abs(i - N) <= D / 2 - dis[x])
      f[x][i] = 1;
  for (i = 0; i < (int)v[x].size(); ++i) {
    int p = v[x][i];
    if (fa[x] == p)
      continue;
    dfs(p);
    for (j = -n + N; j <= n + N; ++j)
      f[x][j] = 1ll * f[x][j] * (f[p][j - 1] + f[p][j + 1]) % Mo;
  }
}
void Dfs(int x) {
  int i, j;
  for (i = -n + N; i <= n + N; ++i)
    if (abs(i - N) <= lim[x])
      f[x][i] = 1;
  for (i = 0; i < (int)v[x].size(); ++i) {
    int p = v[x][i];
    if (fa[x] == p)
      continue;
    Dfs(p);
    for (j = -n + N; j <= n + N; ++j)
      f[x][j] = 1ll * f[x][j] * (f[p][j - 1] + f[p][j + 1]) % Mo;
  }
}
int g[N][N * 2][8], G[N * 2][8];
void Del(int x) {
  int i, j, k, l;
  if (col[x] || lim[x] > 1) {
    for (i = -n + N; i <= n + N; ++i)
      if (abs(i - N) <= lim[x])
        g[x][i][0] = 1;
  } else {
    g[x][N][1] = 1;
    g[x][N - 1][2] = 1;
    g[x][N + 1][4] = 1;
  }
  for (i = 0; i < (int)v[x].size(); ++i) {
    int p = v[x][i];
    if (fa[x] == p)
      continue;
    Del(p);
    memcpy(G, g[x], sizeof(G));
    memset(g[x], 0, sizeof(g[x]));
    for (j = -n + N; j <= n + N; ++j)
      for (k = 0; k < 8; ++k)
        if (G[j][k])
          for (l = 0; l < 8; ++l)
            jia(g[x][j][k | l],
                1ll * G[j][k] * (g[p][j - 1][l] + g[p][j + 1][l]) % Mo);
  }
}
int main() {
  scanf("%d", &n);
  for (i = 1; i < n; ++i) {
    scanf("%d%d", &x, &y);
    v[x].pb(y);
    v[y].pb(x);
  }
  int x = bfs(dis, 1), y = bfs(dis, x);
  for (; y; y = fa[y])
    dia[++dia[0]] = y;
  if (dia[0] & 1) {
    D = dia[0] - 1;
    bfs(dis, dia[D / 2 + 1]);
    dfs(dia[D / 2 + 1]);
    for (i = -n + N; i <= n + N; ++i)
      jia(ans, f[dia[D / 2 + 1]][i]);
    printf("%d\\n", ans);
  } else {
    for (;;)
      ;
    D = dia[0] - 1;
    bfs(Dis, dia[D / 2 + 2]);
    bfs(dis, dia[D / 2 + 1]);
    for (i = 1; i <= n; ++i)
      if (dis[i] < Dis[i])
        col[i] = 1;
    for (i = 1; i <= n; ++i)
      if (col[i])
        lim[i] = D / 2 + 1 - dis[i];
      else
        lim[i] = D / 2 - Dis[i];
    Dfs(dia[D / 2 + 1]);
    for (i = -n + N; i <= n + N; ++i)
      jia(ans, f[dia[D / 2 + 1]][i]);
    for (i = 1; i <= n; ++i)
      if (col[i])
        lim[i] = D / 2 - dis[i];
      else
        lim[i] = D / 2 + 1 - Dis[i];
    memset(f, 0, sizeof(f));
    Dfs(dia[D / 2 + 1]);
    for (i = -n + N; i <= n + N; ++i)
      jia(ans, f[dia[D / 2 + 1]][i]);
    Del(dia[D / 2 + 1]);
    for (i = -n + N; i <= n + N; ++i)
      jian(ans, g[dia[D / 2 + 1]][i][1]), jian(ans, g[dia[D / 2 + 1]][i][2]),
          jian(ans, g[dia[D / 2 + 1]][i][4]);
    printf("%d\\n", ans);
  }
}

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#define ls (t << 1)
#define rs ((t << 1) + 1)
#define mid ((l + r) >> 1)
#define fi first
#define se second
#define mk make_pair
#define pb push_back

#define N 1005
#define M 200005
#define seed 23333
#define Mo 1000000007

using namespace std;
int i, j, m, n, p, k, f[N][N * 2], dis[N], fa[N], Q[N], x, y, dia[N], ans, D,
    col[N], Dis[N], lim[N];
vector<int> v[N];
void jia(int &x, int y) {
  x += y;
  if (x >= Mo)
    x -= Mo;
}
void jian(int &x, int y) {
  x -= y;
  if (x < 0)
    x += Mo;
}
int bfs(int *dis, int x) {
  memset(fa, 0, sizeof(fa));
  for (i = 1; i <= n; ++i)
    dis[i] = -1;
  dis[x] = 0;
  Q[Q[0] = 1] = x;
  int i, l;
  for (l = 1; l <= Q[0]; ++l) {
    int p = Q[l];
    for (i = 0; i < (int)v[p].size(); ++i) {
      int k = v[p][i];
      if (dis[k] != -1)
        continue;
      dis[k] = dis[p] + 1;
      fa[k] = p;
      Q[++Q[0]] = k;
    }
  }
  int now = 1;
  for (i = 1; i <= n; ++i)
    if (dis[now] < dis[i])
      now = i;
  return now;
}
void dfs(int x) {
  int i, j;
  for (i = -n + N; i <= n + N; ++i)
    if (abs(i - N) <= D / 2 - dis[x])
      f[x][i] = 1;
  for (i = 0; i < (int)v[x].size(); ++i) {
    int p = v[x][i];
    if (fa[x] == p)
      continue;
    dfs(p);
    for (j = -n + N; j <= n + N; ++j)
      f[x][j] = 1ll * f[x][j] * (f[p][j - 1] + f[p][j + 1]) % Mo;
  }
}
void Dfs(int x, int tp) {
  int i, j;
  for (i = -n + N; i <= n + N; ++i)
    if (col[x]) {
      if (abs(i - N) <= lim[x])
        f[x][i] = 1;
    } else if (abs(i - N - tp) <= lim[x])
      f[x][i] = 1;
  for (i = 0; i < (int)v[x].size(); ++i) {
    int p = v[x][i];
    if (fa[x] == p)
      continue;
    Dfs(p, tp);
    for (j = -n + N; j <= n + N; ++j)
      f[x][j] = 1ll * f[x][j] * (f[p][j - 1] + f[p][j + 1]) % Mo;
  }
}
int main() {
  scanf("%d", &n);
  for (i = 1; i < n; ++i) {
    scanf("%d%d", &x, &y);
    v[x].pb(y);
    v[y].pb(x);
  }
  int x = bfs(dis, 1), y = bfs(dis, x);
  for (; y; y = fa[y])
    dia[++dia[0]] = y;
  if (dia[0] & 1) {
    D = dia[0] - 1;
    bfs(dis, dia[D / 2 + 1]);
    dfs(dia[D / 2 + 1]);
    for (i = -n + N; i <= n + N; ++i)
      jia(ans, f[dia[D / 2 + 1]][i]);
    printf("%d\\n", ans);
  } else {
    D = dia[0] - 1;
    bfs(Dis, dia[D / 2 + 2]);
    bfs(dis, dia[D / 2 + 1]);
    for (i = 1; i <= n; ++i)
      if (dis[i] < Dis[i])
        col[i] = 1;
    for (i = 1; i <= n; ++i)
      if (col[i])
        lim[i] = D / 2 + 1 - dis[i];
      else
        lim[i] = D / 2 - Dis[i];
    Dfs(dia[D / 2 + 1], 0);
    for (i = -n + N; i <= n + N; ++i)
      jia(ans, f[dia[D / 2 + 1]][i]);
    for (i = 1; i <= n; ++i)
      if (col[i])
        lim[i] = D / 2 - dis[i];
      else
        lim[i] = D / 2 + 1 - Dis[i];
    memset(f, 0, sizeof(f));
    Dfs(dia[D / 2 + 1], 0);
    for (i = -n + N; i <= n + N; ++i)
      jia(ans, f[dia[D / 2 + 1]][i]);
    memset(f, 0, sizeof(f));
    Dfs(dia[D / 2 + 1], -1);
    for (i = -n + N; i <= n + N; ++i)
      jian(ans, f[dia[D / 2 + 1]][i]);
    memset(f, 0, sizeof(f));
    Dfs(dia[D / 2 + 1], 1);
    for (i = -n + N; i <= n + N; ++i)
      jian(ans, f[dia[D / 2 + 1]][i]);
    printf("%d\\n", ans);
  }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i, x) for (int i = 0; i < x; i++)
#define repn(i, x) for (int i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
int n;
vector<int> edge[1005];
P DFS(int v, int u, int d) {
  P ret = mp(d, v);
  rep(i, edge[v].size()) {
    if (edge[v][i] == u)
      continue;
    ret = max(ret, DFS(edge[v][i], v, d + 1));
  }
  return ret;
}
int dist[1005][2];
void DFS2(int v, int u, int d, int ty) {
  dist[v][ty] = d;
  rep(i, edge[v].size()) {
    if (edge[v][i] == u)
      continue;
    DFS2(edge[v][i], v, d + 1, ty);
  }
}
int must, u, v;
bool ok(int x, int val) {
  int D = dist[x][0];
  if ((D + abs(val)) / 2 > (dist[v][0] + 1) / 2)
    return false;
  D = dist[x][1];
  if ((D + abs(val - must)) / 2 > (dist[v][0] + 1) / 2)
    return false;
  return true;
}
ll dp[1005][2005];
ll dfs(int x, int y, int val) {
  if (x == v) {
    if (must == val)
      return 1LL;
    else
      return 0LL;
  }
  if (dp[x][val + 1050] >= 0)
    return dp[x][val + 1050];
  ll ret = 1;
  rep(i, edge[x].size()) {
    if (edge[x][i] == y)
      continue;
    ll add = 0;
    if (ok(edge[x][i], val + 1)) {
      add += dfs(edge[x][i], x, val + 1);
    }
    if (ok(edge[x][i], val - 1)) {
      add += dfs(edge[x][i], x, val - 1);
    }
    add %= mod;
    ret = ret * add % mod;
  }
  return dp[x][val + 1050] = ret;
}
int main() {
  cin >> n;
  rep(i, n - 1) {
    int a, b;
    cin >> a >> b;
    edge[a].pb(b);
    edge[b].pb(a);
  }
  P p = DFS(1, -1, 0);
  P q = DFS(p.sc, -1, 0);
  u = p.sc, v = q.sc;
  DFS2(u, -1, 0, 0);
  DFS2(v, -1, 0, 1);
  if (q.fi % 2 == 0) {
    memset(dp, -1LL, sizeof(dp));
    must = 0;
    cout << dfs(u, -1, 0) << endl;
  } else {
    assert(0);
    ll ans = 0;
    must = 1;
    ans += dfs(u, -1, 0);
    must = -1;
    ans += dfs(u, -1, 0);
    cout << ans % mod << endl;
  }
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i, x) for (int i = 0; i < x; i++)
#define repn(i, x) for (int i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
int n;
vector<int> edge[1005];
P DFS(int v, int u, int d) {
  P ret = mp(d, v);
  rep(i, edge[v].size()) {
    if (edge[v][i] == u)
      continue;
    ret = max(ret, DFS(edge[v][i], v, d + 1));
  }
  return ret;
}
int dist[1005][2];
void DFS2(int v, int u, int d, int ty) {
  dist[v][ty] = d;
  rep(i, edge[v].size()) {
    if (edge[v][i] == u)
      continue;
    DFS2(edge[v][i], v, d + 1, ty);
  }
}
int must, u, v;
bool ok(int x, int val) {
  int D = dist[x][0];
  if ((D + abs(val)) / 2 > (dist[v][0] + 1) / 2)
    return false;
  D = dist[x][1];
  if ((D + abs(val - must)) / 2 > (dist[v][0] + 1) / 2)
    return false;
  return true;
}
ll dp[1005][2005];
ll dfs(int x, int y, int val) {
  if (x == v) {
    if (must == val)
      return 1LL;
    else
      return 0LL;
  }
  if (dp[x][val + 1050] >= 0)
    return dp[x][val + 1050];
  ll ret = 1;
  rep(i, edge[x].size()) {
    if (edge[x][i] == y)
      continue;
    ll add = 0;
    if (ok(edge[x][i], val + 1)) {
      add += dfs(edge[x][i], x, val + 1);
    }
    if (ok(edge[x][i], val - 1)) {
      add += dfs(edge[x][i], x, val - 1);
    }
    add %= mod;
    ret = ret * add % mod;
  }
  return dp[x][val + 1050] = ret;
}

int ok2(int x, int val) {
  int D = dist[x][0];
  if ((D + abs(val)) / 2 > (dist[v][0] + 1) / 2)
    return -1;
  D = dist[x][1];
  if ((D + abs(val - must)) / 2 > (dist[v][0] + 1) / 2)
    return -1;
  if (dist[x][0] < dist[x][1]) {
    int dif = dist[v][0] - dist[x][1];
    if (dif < abs(val))
      return 1;
  } else {
    int dif = dist[v][0] - dist[x][0];
    if (dif < abs(val - must))
      return 2;
  }
  return 0;
}
ll dp2[1005][2005][4];
void dfs2(int x, int y, int val) {
  if (x == v) {
    rep(a, 4) dp2[x][val + 1050][a] = 0;
    if (must == val)
      dp2[x][val + 1050][0] = 1LL;
    return;
  }
  if (dp2[x][val + 1050][0] >= 0)
    return;
  rep(a, 4) dp2[x][val + 1050][a] = 0;
  ll ret[2][4] = {};
  ret[0][ok2(x, val)] = 1LL;
  int cur = 0, nxt = 1;
  rep(i, edge[x].size()) {
    if (edge[x][i] == y)
      continue;
    rep(a, 4) ret[nxt][a] = 0;
    if (ok2(edge[x][i], val + 1) != -1) {
      dfs2(edge[x][i], x, val + 1);
      rep(a, 4) rep(b, 4) ret[nxt][a | b] +=
          ret[cur][a] * dp2[edge[x][i]][val + 1 + 1050][b] % mod;
    }
    if (ok2(edge[x][i], val - 1) != -1) {
      dfs2(edge[x][i], x, val - 1);
      rep(a, 4) rep(b, 4) ret[nxt][a | b] +=
          ret[cur][a] * dp2[edge[x][i]][val - 1 + 1050][b] % mod;
    }
    rep(a, 4) ret[nxt][a] %= mod;
    swap(cur, nxt);
  }
  rep(a, 4) dp2[x][val + 1050][a] = ret[cur][a];
  return;
}
int main() {
  cin >> n;
  rep(i, n - 1) {
    int a, b;
    cin >> a >> b;
    edge[a].pb(b);
    edge[b].pb(a);
  }
  P p = DFS(1, -1, 0);
  P q = DFS(p.sc, -1, 0);
  u = p.sc, v = q.sc;
  DFS2(u, -1, 0, 0);
  DFS2(v, -1, 0, 1);
  if (q.fi % 2 == 0) {
    memset(dp, -1LL, sizeof(dp));
    must = 0;
    cout << dfs(u, -1, 0) << endl;
  } else {
    ll ans = 0;
    memset(dp2, -1LL, sizeof(dp2));
    must = 1;
    dfs2(u, -1, 0);
    for (int i = 0; i < 3; i++)
      ans += dp2[u][1050][i];
    memset(dp2, -1LL, sizeof(dp2));
    must = -1;
    dfs2(u, -1, 0);
    for (int i = 0; i < 3; i++)
      ans += dp2[u][1050][i];
    cout << ans % mod << endl;
  }
}


#include <bits/stdc++.h>
using namespace std;

#define int long long

#define rep(i, n) for (int i = 0; i < (n); i++)
#define pb push_back
#define all(v) (v).begin(), (v).end()
#define fi first
#define se second
typedef vector<int> vint;
typedef pair<int, int> pint;
typedef vector<pint> vpint;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

const int mod = 1000000007;
inline void add(int &a, int b) {
  a += b;
  if (a >= mod)
    a -= mod;
}
int mpow(int n, int m) {
  int ret = 1;
  while (m) {
    if (m & 1)
      ret = ret * n % mod;
    n = n * n % mod;
    m >>= 1;
  }
  return ret;
}
const int FACT_SIZE = 1111111;
int fact[FACT_SIZE];
int inv[FACT_SIZE];
struct fact_exec {
  fact_exec() {
    fact[0] = 1;
    for (int i = 1; i < FACT_SIZE; i++)
      fact[i] = fact[i - 1] * i % mod;
    inv[FACT_SIZE - 1] = mpow(fact[FACT_SIZE - 1], mod - 2);
    for (int i = FACT_SIZE - 2; i >= 0; i--)
      inv[i] = inv[i + 1] * (i + 1) % mod;
  }
} factexec;
int nCk(int n, int k) {
  if (n < 0 | k < 0 || k > n)
    return 0;
  return fact[n] * inv[k] % mod * inv[n - k] % mod;
}
int nPk(int n, int k) {
  if (n < 0 || k < 0 || k > n)
    return 0;
  return fact[n] * inv[n - k] % mod;
}

int N;
vint G[1111];

int dist[1111];

void dfs(int v, int p, int d) {
  dist[v] = d;
  for (auto u : G[v]) {
    if (u == p)
      continue;
    dfs(u, v, d + 1);
  }
}

int D;
int X;
int dp[1111][1111];
void dfs2(int v, int p, int d) {
  rep(i, D / 2 + 1) dp[v][i] = 1;
  for (auto u : G[v]) {
    if (u == p)
      continue;
    dfs2(u, v, d + 1);
    rep(i, D / 2 + 1) dp[v][i] = dp[v][i] * (dp[u][i] + dp[u][i + 1]) % mod;
  }
  rep(i, D / 2 + 1) if (i > X || d - i > D / 2 - X) dp[v][i] = 0;
}
void solve(int c) {
  int ans = 0;
  for (X = 0; X <= D / 2; X++) {
    memset(dp, 0, sizeof(dp));
    dfs2(c, -1, 0);
    add(ans, dp[c][0]);
  }
  cout << ans << endl;
}

signed main() {

  cin >> N;
  rep(i, N - 1) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    G[a].pb(b);
    G[b].pb(a);
  }

  dfs(0, -1, 0);
  int v = 0;
  rep(i, N) if (dist[i] > dist[v]) v = i;
  dfs(v, -1, 0);

  int u = 0;
  rep(i, N) if (dist[i] > dist[u]) u = i;

  vint latte(N);
  rep(i, N) latte[i] = dist[i];
  dfs(u, -1, 0);
  rep(i, N) chmax(latte[i], dist[i]);

  vint lis;
  rep(i, N) if (latte[i] <= (dist[v] + 1) / 2) lis.pb(i);

  D = dist[v];

  if (lis.size() == 1) {
    solve(lis[0]);
  } else {
    int u = lis[0], v = lis[1];

    vint x(N), y(N), z(N), w(N);

    for (X = 0; X <= D / 2; X++) {
      memset(dp, 0, sizeof(dp));
      dfs2(u, v, 0);
      x[X] = dp[u][0];

      memset(dp, 0, sizeof(dp));
      dfs2(v, u, 0);
      y[X] = dp[v][0];
    }

    D++;
    for (X = 0; X <= D / 2; X++) {
      memset(dp, 0, sizeof(dp));
      dfs2(u, v, 0);
      z[X] = dp[u][0];

      memset(dp, 0, sizeof(dp));
      dfs2(v, u, 0);
      w[X] = dp[v][0];
    }

    D--;
    z[0] = w[0] = 0;
    for (int i = 1; i < N; i++)
      z[i] = (z[i] - x[i] - x[i - 1] + mod * 2) % mod;
    for (int i = 1; i < N; i++)
      w[i] = (w[i] - y[i] - y[i - 1] + mod * 2) % mod;

    int ans = 0;
    for (int i = 0; i <= D / 2; i++) {
      for (int j = 0; j <= D / 2; j++) {
        int a = i;
        int b = D / 2 - i;
        int c = j;
        int d = D / 2 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, x[i] * y[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, x[i] * y[j] % mod);
      }
    }

    for (int i = 0; i <= D / 2; i++) {
      for (int j = 0; j <= D / 2 + 1; j++) {
        int a = i;
        int b = D / 2 - i;
        int c = j;
        int d = D / 2 + 1 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, x[i] * w[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, x[i] * w[j] % mod);
      }
    }

    for (int i = 0; i <= D / 2 + 1; i++) {
      for (int j = 0; j <= D / 2 + 1; j++) {
        int a = i;
        int b = D / 2 + 1 - i;
        int c = j;
        int d = D / 2 + 1 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, z[i] * w[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, z[i] * w[j] % mod);
      }
    }

    for (int i = 0; i <= D / 2 + 1; i++) {
      for (int j = 0; j <= D / 2; j++) {
        int a = i;
        int b = D / 2 + 1 - i;
        int c = j;
        int d = D / 2 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, z[i] * y[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, z[i] * y[j] % mod);
      }
    }

    cout << ans << endl;
  }
  return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define int long long

#define rep(i, n) for (int i = 0; i < (n); i++)
#define pb push_back
#define all(v) (v).begin(), (v).end()
#define fi first
#define se second
typedef vector<int> vint;
typedef pair<int, int> pint;
typedef vector<pint> vpint;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

const int mod = 1000000007;
inline void add(int &a, int b) {
  a += b;
  if (a >= mod)
    a -= mod;
}
int mpow(int n, int m) {
  int ret = 1;
  while (m) {
    if (m & 1)
      ret = ret * n % mod;
    n = n * n % mod;
    m >>= 1;
  }
  return ret;
}
const int FACT_SIZE = 1111111;
int fact[FACT_SIZE];
int inv[FACT_SIZE];
struct fact_exec {
  fact_exec() {
    fact[0] = 1;
    for (int i = 1; i < FACT_SIZE; i++)
      fact[i] = fact[i - 1] * i % mod;
    inv[FACT_SIZE - 1] = mpow(fact[FACT_SIZE - 1], mod - 2);
    for (int i = FACT_SIZE - 2; i >= 0; i--)
      inv[i] = inv[i + 1] * (i + 1) % mod;
  }
} factexec;
int nCk(int n, int k) {
  if (n < 0 | k < 0 || k > n)
    return 0;
  return fact[n] * inv[k] % mod * inv[n - k] % mod;
}
int nPk(int n, int k) {
  if (n < 0 || k < 0 || k > n)
    return 0;
  return fact[n] * inv[n - k] % mod;
}

int N;
vint G[1111];

int dist[1111];

void dfs(int v, int p, int d) {
  dist[v] = d;
  for (auto u : G[v]) {
    if (u == p)
      continue;
    dfs(u, v, d + 1);
  }
}

int D;
int X;
int dp[1111][1111];
void dfs2(int v, int p, int d) {

  int l = max(0ll, X + d - D / 2);

  for (int i = l; i <= X; i++)
    dp[v][i] = 1;
  for (auto u : G[v]) {
    if (u == p)
      continue;
    dfs2(u, v, d + 1);
    for (int i = l; i <= X; i++)
      dp[v][i] = dp[v][i] * (dp[u][i] + dp[u][i + 1]) % mod;
  }
}
void solve(int c) {
  int ans = 0;
  for (X = 0; X <= D / 2; X++) {
    memset(dp, 0, sizeof(dp));
    dfs2(c, -1, 0);
    add(ans, dp[c][0]);
  }
  cout << ans << endl;
}

signed main() {

  cin >> N;
  rep(i, N - 1) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    G[a].pb(b);
    G[b].pb(a);
  }

  dfs(0, -1, 0);
  int v = 0;
  rep(i, N) if (dist[i] > dist[v]) v = i;
  dfs(v, -1, 0);

  int u = 0;
  rep(i, N) if (dist[i] > dist[u]) u = i;

  vint latte(N);
  rep(i, N) latte[i] = dist[i];
  dfs(u, -1, 0);
  rep(i, N) chmax(latte[i], dist[i]);

  vint lis;
  rep(i, N) if (latte[i] <= (dist[v] + 1) / 2) lis.pb(i);

  D = dist[v];

  if (lis.size() == 1) {
    solve(lis[0]);
  } else {
    int u = lis[0], v = lis[1];

    vint x(N), y(N), z(N), w(N);

    for (X = 0; X <= D / 2; X++) {
      memset(dp, 0, sizeof(dp));
      dfs2(u, v, 0);
      x[X] = dp[u][0];

      memset(dp, 0, sizeof(dp));
      dfs2(v, u, 0);
      y[X] = dp[v][0];
    }

    D++;
    for (X = 0; X <= D / 2; X++) {
      memset(dp, 0, sizeof(dp));
      dfs2(u, v, 0);
      z[X] = dp[u][0];

      memset(dp, 0, sizeof(dp));
      dfs2(v, u, 0);
      w[X] = dp[v][0];
    }

    D--;
    z[0] = w[0] = 0;
    for (int i = 1; i < N; i++)
      z[i] = (z[i] - x[i] - x[i - 1] + mod * 2) % mod;
    for (int i = 1; i < N; i++)
      w[i] = (w[i] - y[i] - y[i - 1] + mod * 2) % mod;

    int ans = 0;
    for (int i = 0; i <= D / 2; i++) {
      for (int j = 0; j <= D / 2; j++) {
        int a = i;
        int b = D / 2 - i;
        int c = j;
        int d = D / 2 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, x[i] * y[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, x[i] * y[j] % mod);
      }
    }

    for (int i = 0; i <= D / 2; i++) {
      for (int j = 0; j <= D / 2 + 1; j++) {
        int a = i;
        int b = D / 2 - i;
        int c = j;
        int d = D / 2 + 1 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, x[i] * w[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, x[i] * w[j] % mod);
      }
    }

    for (int i = 0; i <= D / 2 + 1; i++) {
      for (int j = 0; j <= D / 2 + 1; j++) {
        int a = i;
        int b = D / 2 + 1 - i;
        int c = j;
        int d = D / 2 + 1 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, z[i] * w[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, z[i] * w[j] % mod);
      }
    }

    for (int i = 0; i <= D / 2 + 1; i++) {
      for (int j = 0; j <= D / 2; j++) {
        int a = i;
        int b = D / 2 + 1 - i;
        int c = j;
        int d = D / 2 - j;
        if (a + d <= D / 2 + 1 && b + c + 1 <= D / 2 + 1)
          add(ans, z[i] * y[j] % mod);
        if (a + d + 1 <= D / 2 + 1 && b + c <= D / 2 + 1)
          add(ans, z[i] * y[j] % mod);
      }
    }

    cout << ans << endl;
  }
  return 0;
}


// ba mei zi !

#include <bits/stdc++.h>

#define HEAP priority_queue
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define per(i, n) for (int i = (n)-1; i >= 0; --i)
#define forn(i, l, r) for (int i = (l); i <= (r); ++i)
#define nrof(i, r, l) for (int i = (r); i >= (l); --i)
#define FOR(a, b) for (auto(a) : (b))
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define X first
#define Y second
#define eps 1e-6
#define pi 3.1415926535897932384626433832795
#define SZ(x) (int)x.size()
#define ALL(x) x.begin(), x.end()
#define FILL(a, b) memset((a), (b), sizeof((a)))
#define MCPY(a, b) memcpy((a), (b), sizeof((b)))

using namespace std;

typedef long long LL;
typedef double flt;
typedef vector<int> vi;
typedef vector<LL> vl;
typedef pair<int, int> pii;
typedef pair<int, LL> pil;
typedef pair<LL, int> pli;
typedef pair<LL, LL> pll;
typedef vector<pil> vil;
typedef vector<pii> vii;
typedef vector<pli> vli;
typedef vector<pll> vll;

const int iinf = 1e9 + 7;
const LL linf = 1ll << 60;
const flt dinf = 1e60;

template <typename T> inline void scf(T &x) {
  bool f = 0;
  x = 0;
  char c = getchar();
  while ((c < '0' || c > '9') && c != '-')
    c = getchar();
  if (c == '-') {
    f = 1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  if (f)
    x = -x;
  return;
}

template <typename T1, typename T2> void scf(T1 &x, T2 &y) {
  scf(x);
  return scf(y);
}

template <typename T1, typename T2, typename T3> void scf(T1 &x, T2 &y, T3 &z) {
  scf(x);
  scf(y);
  return scf(z);
}

template <typename T1, typename T2, typename T3, typename T4>
void scf(T1 &x, T2 &y, T3 &z, T4 &w) {
  scf(x);
  scf(y);
  scf(z);
  return scf(w);
}

inline char mygetchar() {
  char c = getchar();
  while (c == ' ' || c == '\\n')
    c = getchar();
  return c;
}

template <typename T> void chkmax(T &x, const T &y) {
  if (y > x)
    x = y;
  return;
}

template <typename T> void chkmin(T &x, const T &y) {
  if (y < x)
    x = y;
  return;
}

#ifdef ONLINE_JUDGE
#define debug(x, c) ;
#else
#define DEBUG
#define debug(x, c) cerr << #x << "=" << x << c;
#endif

//---------------------------head----------------------------

const int N = 1e3 + 100;
const int mod = 1e9 + 7;

int n, diameter_length, min_D;
int dp[N][N], tag[N][N], current_time;
vi g[N];
vi diameter_path;

namespace TREE {
int par[N], dep[N];

void dfs(int u = 1, int fa = 0) {
  par[u] = fa;
  dep[u] = dep[fa] + 1;
  for (int v : g[u])
    if (v != fa)
      dfs(v, u);
  return;
}

void get_diameter() {
  dfs();
  int mx = -1, S, T;
  forn(i, 1, n) if (dep[i] > mx) mx = dep[i], S = i;
  dfs(S);
  mx = -1;
  forn(i, 1, n) if (dep[i] > mx) mx = dep[i], T = i;

  diameter_length = dep[T] - 1;
  min_D = dep[T] >> 1;

  int u = T;
  while (u != S)
    diameter_path.pb(u), u = par[u];
  diameter_path.pb(S);
  return;
}
} // namespace TREE

void MEI() {
  scf(n);
  rep(i, n - 1) {
    int u, v;
    scf(u, v);
    g[u].pb(v);
    g[v].pb(u);
  }

  TREE::get_diameter();
  return;
}

namespace Bamboo {
void solve() {
  for (;;)
    ;
  dp[0][0] = 1;
  forn(i, 1, n - 1) {
    dp[i][0] = dp[i][i] = 1;
    forn(j, 1, i - 1) dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
  }
  printf("%d\\n", dp[n - 1][min_D] * 2 % mod);
  return;
}
} // namespace Bamboo

void DP(int u, int par, int max_down, int max_up) {
  if (tag[u][max_down] == current_time)
    return;

  tag[u][max_down] = current_time;
  int &t = dp[u][max_down];
  t = 1;

  for (int v : g[u])
    if (v != par) {
      int foo = 0;
      if (max_down)
        DP(v, u, max_down - 1, max_up), foo += dp[v][max_down - 1];
      if (max_up)
        DP(v, u, max_down, max_up - 1), foo += dp[v][max_down];
      t = 1ll * t * foo % mod;
    }
  return;
}

namespace Odd {
int ans = 0;
int root1, root2;

void case1() {
  rep(down2, min_D) {
    int up1 = min_D - 1 - down2;
    int up2 = up1, down1 = down2;

    current_time++;
    DP(root2, root1, down2, up2);
    int foo = dp[root2][down2];

    current_time++;
    DP(root1, root2, down1, up1);
    foo = 1ll * foo * dp[root1][down1] % mod;
    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void case2() {
  forn(down2, 1, min_D - 1) {
    int up2 = min_D - 1 - down2;
    int up1 = min_D - down2;
    int down1 = min_D - 1 - up1;

    current_time++;
    DP(root2, root1, down2, up2);
    int foo = dp[root2][down2];

    current_time++;
    DP(root1, root2, down1, up1);
    foo = 1ll * foo * dp[root1][down1] % mod;
    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void case3() {
  rep(down2, min_D) {
    int up1 = min_D - down2;
    int up2 = up1 - 1;
    int down1 = min_D - up1;

    current_time++;
    DP(root2, root1, down2, up2);
    int foo = dp[root2][down2];

    current_time++;
    DP(root1, root2, down1, up1);
    LL bar = dp[root1][down1];
    if (down1 > 0) {
      current_time++;
      DP(root1, root2, down1 - 1, up1);
      bar += mod - dp[root1][down1 - 1];
    }
    if (up1 > 0) {
      current_time++;
      DP(root1, root2, down1, up1 - 1);
      bar += mod - dp[root1][down1];
    }

    foo = 1ll * foo * bar % mod;
    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void case4() {
  forn(down2, 1, min_D) {
    int up1 = min_D - down2;
    int up2 = up1;
    int down1 = min_D - 1 - up1;

    current_time++;
    DP(root2, root1, down2, up2);
    LL foo = dp[root2][down2];
    if (up2 > 0) {
      current_time++;
      DP(root2, root1, down2, up2 - 1);
      foo += mod - dp[root2][down2];
    }
    if (down2 > 0) {
      current_time++;
      DP(root2, root1, down2 - 1, up2);
      foo += mod - dp[root2][down2 - 1];
    }

    current_time++;
    DP(root1, root2, down1, up1);
    foo = foo * 1ll * dp[root1][down1] % mod;

    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void solve() {
  root1 = diameter_path[min_D - 1];
  root2 = diameter_path[min_D];
  case1();
  case2();
  case3();
  case4();
  ans += ans;
  if (ans >= mod)
    ans -= mod;
  printf("%d\\n", ans);
  return;
}
} // namespace Odd

namespace Even {
void solve() {
  int root = diameter_path[min_D];
  int ans = 0;
  forn(max_down, 0, min_D) {
    current_time++;
    DP(root, 0, max_down, min_D - max_down);
    ans += dp[root][max_down];
    if (ans >= mod)
      ans -= mod;
  }
  printf("%d\\n", ans);
  return;
}
} // namespace Even

void ZI() {
  if (diameter_length == n - 1)
    Bamboo::solve();
  else if (diameter_length & 1)
    Odd::solve();
  else
    Even::solve();
  return;
}

/*
   Main
   code
   is
   over
   .
   If
   you
   are
   in
   a
   hurry
   trying
   to
   hack
   me
   you
   don't
   need
   to
   read
   the
   part
   left
   .
   Trust
   me
   .
   It
   is
   useless
   .
   My
   code
   always
gets
a
failed
system
test
,
so
it
will
be
pretty
easy
for
you
to
hack
me
.
Just
find
a
test
case
and
hack
.
Wish
you
all
happy
hack
.
 _____
/     \\
| . . |
|     |
|  |  |
| --- |
| \\_/ |
\\_____/

*/

#ifdef DEBUG

struct I {
  int x;
  I() {}
  I(int y) : x(y) {}
  bool operator<(const I &a) const { return x < a.x; }
};

pair<I, LL> time_limit_exceeded;
const bool FLAG = 1;
static vector<I> wrong_answer;
I *RP = new I;

I FUCK = min(I{*RP}, I{0});
static int memory_limit_exceeded[10];
vi O() {
  cout << FUCK.x << endl;
  vi ert;
  int x = 0;
  x = (int)hypot(3.0, 4.0);
  ert.pb(x);
  if (x & 1)
    exit(0);
  auto t = lower_bound(ALL(ert), 5);
  static list<int> runtime_error_;
  return ert;
}
#endif // DEBUG

#define MEI int
#define ZI main
MEI ZI() {
#undef MEI
#undef ZI

  MEI();
  ZI();

#define BA return
#define MEI 0
#define ZI ;
  BA MEI ZI
#undef BA
#undef MEI
#undef ZI
}

// ba mei zi !

#include <bits/stdc++.h>

#define HEAP priority_queue
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define per(i, n) for (int i = (n)-1; i >= 0; --i)
#define forn(i, l, r) for (int i = (l); i <= (r); ++i)
#define nrof(i, r, l) for (int i = (r); i >= (l); --i)
#define FOR(a, b) for (auto(a) : (b))
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define X first
#define Y second
#define eps 1e-6
#define pi 3.1415926535897932384626433832795
#define SZ(x) (int)x.size()
#define ALL(x) x.begin(), x.end()
#define FILL(a, b) memset((a), (b), sizeof((a)))
#define MCPY(a, b) memcpy((a), (b), sizeof((b)))

using namespace std;

typedef long long LL;
typedef double flt;
typedef vector<int> vi;
typedef vector<LL> vl;
typedef pair<int, int> pii;
typedef pair<int, LL> pil;
typedef pair<LL, int> pli;
typedef pair<LL, LL> pll;
typedef vector<pil> vil;
typedef vector<pii> vii;
typedef vector<pli> vli;
typedef vector<pll> vll;

const int iinf = 1e9 + 7;
const LL linf = 1ll << 60;
const flt dinf = 1e60;

template <typename T> inline void scf(T &x) {
  bool f = 0;
  x = 0;
  char c = getchar();
  while ((c < '0' || c > '9') && c != '-')
    c = getchar();
  if (c == '-') {
    f = 1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  if (f)
    x = -x;
  return;
}

template <typename T1, typename T2> void scf(T1 &x, T2 &y) {
  scf(x);
  return scf(y);
}

template <typename T1, typename T2, typename T3> void scf(T1 &x, T2 &y, T3 &z) {
  scf(x);
  scf(y);
  return scf(z);
}

template <typename T1, typename T2, typename T3, typename T4>
void scf(T1 &x, T2 &y, T3 &z, T4 &w) {
  scf(x);
  scf(y);
  scf(z);
  return scf(w);
}

inline char mygetchar() {
  char c = getchar();
  while (c == ' ' || c == '\\n')
    c = getchar();
  return c;
}

template <typename T> void chkmax(T &x, const T &y) {
  if (y > x)
    x = y;
  return;
}

template <typename T> void chkmin(T &x, const T &y) {
  if (y < x)
    x = y;
  return;
}

#ifdef ONLINE_JUDGE
#define debug(x, c) ;
#else
#define DEBUG
#define debug(x, c) cerr << #x << "=" << x << c;
#endif

//---------------------------head----------------------------

const int N = 1e3 + 100;
const int mod = 1e9 + 7;

int n, diameter_length, min_D;
int dp[N][N], tag[N][N], current_time;
vi g[N];
vi diameter_path;

namespace TREE {
int par[N], dep[N];

void dfs(int u = 1, int fa = 0) {
  par[u] = fa;
  dep[u] = dep[fa] + 1;
  for (int v : g[u])
    if (v != fa)
      dfs(v, u);
  return;
}

void get_diameter() {
  dfs();
  int mx = -1, S, T;
  forn(i, 1, n) if (dep[i] > mx) mx = dep[i], S = i;
  dfs(S);
  mx = -1;
  forn(i, 1, n) if (dep[i] > mx) mx = dep[i], T = i;

  diameter_length = dep[T] - 1;
  min_D = dep[T] >> 1;

  int u = T;
  while (u != S)
    diameter_path.pb(u), u = par[u];
  diameter_path.pb(S);
  return;
}
} // namespace TREE

void MEI() {
  scf(n);
  rep(i, n - 1) {
    int u, v;
    scf(u, v);
    g[u].pb(v);
    g[v].pb(u);
  }

  TREE::get_diameter();
  return;
}

namespace Bamboo {
void solve() {
  dp[0][0] = 1;
  forn(i, 1, n - 1) {
    dp[i][0] = dp[i][i] = 1;
    forn(j, 1, i - 1) dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
  }
  printf("%d\\n", (n & 1) ? dp[n - 1][min_D] : (dp[n - 1][min_D] * 2 % mod));
  return;
}
} // namespace Bamboo

void DP(int u, int par, int max_down, int max_up) {
  if (tag[u][max_down] == current_time)
    return;

  tag[u][max_down] = current_time;
  int &t = dp[u][max_down];
  t = 1;

  for (int v : g[u])
    if (v != par) {
      int foo = 0;
      if (max_down)
        DP(v, u, max_down - 1, max_up), foo += dp[v][max_down - 1];
      if (max_up)
        DP(v, u, max_down, max_up - 1), foo += dp[v][max_down];
      t = 1ll * t * foo % mod;
    }
  return;
}

namespace Odd {
int ans = 0;
int root1, root2;

void case1() {
  rep(down2, min_D) {
    int up1 = min_D - 1 - down2;
    int up2 = up1, down1 = down2;

    current_time++;
    DP(root2, root1, down2, up2);
    int foo = dp[root2][down2];

    current_time++;
    DP(root1, root2, down1, up1);
    foo = 1ll * foo * dp[root1][down1] % mod;
    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void case2() {
  forn(down2, 1, min_D - 1) {
    int up2 = min_D - 1 - down2;
    int up1 = min_D - down2;
    int down1 = min_D - 1 - up1;

    current_time++;
    DP(root2, root1, down2, up2);
    int foo = dp[root2][down2];

    current_time++;
    DP(root1, root2, down1, up1);
    foo = 1ll * foo * dp[root1][down1] % mod;
    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void case3() {
  rep(down2, min_D) {
    int up1 = min_D - down2;
    int up2 = up1 - 1;
    int down1 = min_D - up1;

    current_time++;
    DP(root2, root1, down2, up2);
    int foo = dp[root2][down2];

    current_time++;
    DP(root1, root2, down1, up1);
    LL bar = dp[root1][down1];
    if (down1 > 0) {
      current_time++;
      DP(root1, root2, down1 - 1, up1);
      bar += mod - dp[root1][down1 - 1];
    }
    if (up1 > 0) {
      current_time++;
      DP(root1, root2, down1, up1 - 1);
      bar += mod - dp[root1][down1];
    }

    foo = 1ll * foo * bar % mod;
    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void case4() {
  forn(down2, 1, min_D) {
    int up1 = min_D - down2;
    int up2 = up1;
    int down1 = min_D - 1 - up1;

    current_time++;
    DP(root2, root1, down2, up2);
    LL foo = dp[root2][down2];
    if (up2 > 0) {
      current_time++;
      DP(root2, root1, down2, up2 - 1);
      foo += mod - dp[root2][down2];
    }
    if (down2 > 0) {
      current_time++;
      DP(root2, root1, down2 - 1, up2);
      foo += mod - dp[root2][down2 - 1];
    }

    current_time++;
    DP(root1, root2, down1, up1);
    foo = foo * 1ll * dp[root1][down1] % mod;

    ans += foo;
    if (ans >= mod)
      ans -= mod;
  }
  debug(ans, '\\n') return;
}

void solve() {
  root1 = diameter_path[min_D - 1];
  root2 = diameter_path[min_D];
  case1();
  case2();
  case3();
  case4();
  ans += ans;
  if (ans >= mod)
    ans -= mod;
  printf("%d\\n", ans);
  return;
}
} // namespace Odd

namespace Even {
void solve() {
  int root = diameter_path[min_D];
  int ans = 0;
  forn(max_down, 0, min_D) {
    current_time++;
    DP(root, 0, max_down, min_D - max_down);
    ans += dp[root][max_down];
    if (ans >= mod)
      ans -= mod;
  }
  printf("%d\\n", ans);
  return;
}
} // namespace Even

void ZI() {
  if (diameter_length == n - 1)
    Bamboo::solve();
  else if (diameter_length & 1)
    Odd::solve();
  else
    Even::solve();
  return;
}

/*
   Main
   code
   is
   over
   .
   If
   you
   are
   in
   a
   hurry
   trying
   to
   hack
   me
   you
   don't
   need
   to
   read
   the
   part
   left
   .
   Trust
   me
   .
   It
   is
   useless
   .
   My
   code
   always
gets
a
failed
system
test
,
so
it
will
be
pretty
easy
for
you
to
hack
me
.
Just
find
a
test
case
and
hack
.
Wish
you
all
happy
hack
.
 _____
/     \\
| . . |
|     |
|  |  |
| --- |
| \\_/ |
\\_____/

*/

#ifdef DEBUG

struct I {
  int x;
  I() {}
  I(int y) : x(y) {}
  bool operator<(const I &a) const { return x < a.x; }
};

pair<I, LL> time_limit_exceeded;
const bool FLAG = 1;
static vector<I> wrong_answer;
I *RP = new I;

I FUCK = min(I{*RP}, I{0});
static int memory_limit_exceeded[10];
vi O() {
  cout << FUCK.x << endl;
  vi ert;
  int x = 0;
  x = (int)hypot(3.0, 4.0);
  ert.pb(x);
  if (x & 1)
    exit(0);
  auto t = lower_bound(ALL(ert), 5);
  static list<int> runtime_error_;
  return ert;
}
#endif // DEBUG

#define MEI int
#define ZI main
MEI ZI() {
#undef MEI
#undef ZI

  MEI();
  ZI();

#define BA return
#define MEI 0
#define ZI ;
  BA MEI ZI
#undef BA
#undef MEI
#undef ZI
}


#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
#define N 1200

const LL mod = 1000000007;
LL n, rt, q[N], tot, len, head[N], f[N][N], fa[N], dep[N];
bool vis[N];
struct edge {
  LL v, nxt;
} e[N << 1];

void add(LL x, LL y) {
  e[++tot].v = y;
  e[tot].nxt = head[x];
  head[x] = tot;
}

LL bfs(LL s) {
  memset(vis, 0, sizeof vis);
  LL tt = 0, ww = 1;
  q[1] = s;
  vis[s] = 1;
  while (tt < ww) {
    LL u = q[++tt];
    for (LL i = head[u], v; i; i = e[i].nxt)
      if (!vis[v = e[i].v]) {
        vis[v] = 1;
        q[++ww] = v;
      }
  }
  return q[n];
}

void dfs(LL u) {
  for (LL i = head[u], v; i; i = e[i].nxt)
    if ((v = e[i].v) != fa[u]) {
      fa[v] = u;
      dfs(v);
    }
}

void dp(LL u) {
  dep[u] = dep[fa[u]] + 1;
  for (LL i = 0; i <= len + 1 - dep[u]; ++i)
    f[u][i] = 1;
  for (LL i = head[u], v; i; i = e[i].nxt)
    if ((v = e[i].v) != fa[u]) {
      fa[v] = u;
      dp(v);
      for (LL j = 0; j <= len; ++j) {
        f[u][j] = f[u][j] * (f[v][j] + (j ? f[v][j - 1] : 0)) % mod;
      }
    }
}

int main() {
  scanf("%lld", &n);
  for (LL i = 1; i < n; ++i) {
    LL x, y;
    scanf("%lld%lld", &x, &y);
    add(x, y);
    add(y, x);
  }
  LL S = bfs(1);
  LL T = bfs(S);
  dfs(S);
  len = 0;
  for (LL i = T; i != S; i = fa[i])
    ++len;
  if (len & 1) {
    assert(0);
  } else {
    len /= 2;
    rt = T;
    for (int i = 1; i <= len; ++i)
      rt = fa[rt];
    memset(fa, 0, sizeof fa);
    dp(rt);
    LL ans = 0;
    for (LL i = 0; i <= len; ++i)
      ans = (ans + f[rt][i]) % mod;
    printf("%lld\\n", ans);
  }

  return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
#define N 1200

const LL mod = 1000000007;
LL n, rt, rt1, rt2, q[N], tot, len, head[N], f[N][N][2], fa[N], dep[N];
bool vis[N];
struct edge {
  LL v, nxt;
} e[N << 1];

void add(LL x, LL y) {
  e[++tot].v = y;
  e[tot].nxt = head[x];
  head[x] = tot;
}

LL bfs(LL s) {
  memset(vis, 0, sizeof vis);
  LL tt = 0, ww = 1;
  q[1] = s;
  vis[s] = 1;
  while (tt < ww) {
    LL u = q[++tt];
    for (LL i = head[u], v; i; i = e[i].nxt)
      if (!vis[v = e[i].v]) {
        vis[v] = 1;
        q[++ww] = v;
      }
  }
  return q[n];
}

void dfs(LL u) {
  for (LL i = head[u], v; i; i = e[i].nxt)
    if ((v = e[i].v) != fa[u]) {
      fa[v] = u;
      dfs(v);
    }
}

void dp(LL u) {
  for (LL i = 0; i <= len - dep[u]; ++i)
    f[u][i][0] = f[u][i][1] = f[u][i + 1][1] = 1;
  for (LL i = head[u], v; i; i = e[i].nxt)
    if ((v = e[i].v) != fa[u]) {
      dep[v] = dep[u] + 1;
      fa[v] = u;
      dp(v);
      for (LL j = 0; j <= len; ++j) {
        f[u][j][0] = f[u][j][0] * (f[v][j][0] + (j ? f[v][j - 1][0] : 0)) % mod;
        f[u][j][1] = f[u][j][1] * (f[v][j][1] + (j ? f[v][j - 1][1] : 0)) % mod;
      }
    }
}

int main() {
  scanf("%lld", &n);
  for (LL i = 1; i < n; ++i) {
    LL x, y;
    scanf("%lld%lld", &x, &y);
    add(x, y);
    add(y, x);
  }
  LL S = bfs(1);
  LL T = bfs(S);
  dfs(S);
  len = 0;
  for (LL i = T; i != S; i = fa[i])
    ++len;
  if (len & 1) {
    len /= 2;
    rt1 = T;
    for (int i = 1; i <= len; ++i)
      rt1 = fa[rt1];
    rt2 = fa[rt1];
    memset(fa, 0, sizeof fa);
    fa[rt1] = rt2;
    fa[rt2] = rt1;
    dp(rt1);
    dp(rt2);
    LL ans = 0;
#define f1 f[rt1]
#define f2 f[rt2]
    for (LL i = 0; i <= len; ++i)
      ans = (ans + f1[i][0] * (f2[i][1] + f2[i + 1][1] - f2[i][0]) % mod +
             f2[i][0] * (f1[i][1] + f1[i + 1][1] - f1[i][0]) % mod -
             f1[i][0] * f2[i + 1][0] % mod - f1[i + 1][0] * f2[i][0] % mod +
             mod * 10) %
            mod;
    printf("%lld\\n", ans);
  } else {
    len /= 2;
    rt = T;
    for (int i = 1; i <= len; ++i)
      rt = fa[rt];
    memset(fa, 0, sizeof fa);
    dp(rt);
    LL ans = 0;
    for (LL i = 0; i <= len; ++i)
      ans = (ans + f[rt][i][0]) % mod;
    printf("%lld\\n", ans);
  }

  return 0;
}