Recently Bob invented a new game with a tree (we should remind you, that a tree is a connected graph without cycles): he deletes any (possibly, zero) amount of edges of the tree, and counts the product of sizes of the connected components left after the deletion. Your task is to find out the maximum number that Bob can get in his new game for a given tree.

Input

The first input line contains integer number n (1 ≤ n ≤ 700) — amount of vertices in the tree. The following n - 1 lines contain the description of the edges. Each line contains the pair of vertices' indexes, joined by an edge, ai, bi (1 ≤ ai, bi ≤ n). It's guaranteed that the graph described in the input is a tree.

Output

Output the only number — the maximum product of sizes of the connected components, that Bob can get after deleting some of the tree's edges.

Examples

Input

5
1 2
2 3
3 4
4 5


Output

6

Input

8
1 2
1 3
2 4
2 5
3 6
3 7
6 8


Output

18

Input

3
1 2
1 3


Output

3
#include <bits/stdc++.h>
using namespace std;
vector<string> dp, ilo;
string NaStr(int x) {
  if (x == 0) return "0";
  string odp = "";
  while (x != 0) {
    odp = (char)(x % 10 + '0') + odp;
    x /= 10;
  }
  return odp;
}
string Maximum(string a, string b) {
  int n = a.size(), m = b.size();
  if (n > m) return a;
  if (n == m && a > b) return a;
  return b;
}
string Dodaj(string a, string b) {
  if (a.size() > b.size()) swap(a, b);
  while (b.size() != a.size()) a = "0" + a;
  int n = a.size();
  string wyn = "";
  int prze = 0;
  for (int i = n - 1; i >= 0; --i) {
    int x = (a[i] - '0') + (b[i] - '0') + prze;
    wyn += (char)(x % 10 + '0');
    prze = x / 10;
  }
  if (prze != 0) wyn += (char)(prze + '0');
  reverse(wyn.begin(), wyn.end());
  return wyn;
}
string MnozCyf(int a, string b) {
  if (a == 0) return "0";
  int n = b.size();
  string wyn = "";
  int prze = 0;
  for (int i = n - 1; i >= 0; --i) {
    int x = a * (b[i] - '0') + prze;
    wyn += (char)(x % 10 + '0');
    prze = x / 10;
  }
  if (prze != 0) wyn += (char)(prze + '0');
  reverse(wyn.begin(), wyn.end());
  return wyn;
}
string Mnoz(string a, string b) {
  if (a == "0" || b == "0") return "0";
  if (a.size() > b.size()) swap(a, b);
  int n = a.size(), m = b.size();
  string wyn = "0";
  for (int i = n - 1; i >= 0; --i) {
    string dod = MnozCyf(a[i] - '0', b);
    for (int j = i + 1; j < n; ++j) dod += "0";
    wyn = Dodaj(wyn, dod);
  }
  return wyn;
}
bool por(int a, int b) {
  string x = Mnoz(ilo[a], dp[b]);
  string y = Mnoz(dp[a], ilo[b]);
  if (x != y) {
    if (Maximum(x, y) == x) return true;
    return false;
  }
  if (a < b) return true;
  return false;
}
void dfs(vector<vector<int> >& T, int akt, int oj) {
  for (int i = 0; i < T[akt].size(); ++i)
    if (T[akt][i] != oj) dfs(T, T[akt][i], akt);
  if (T[akt].size() == 1 && akt != 0) {
    dp[akt] = "1";
    ilo[akt] = "1";
    return;
  }
  if (akt != 0) {
    int nr_oj = 0;
    while (T[akt][nr_oj] != oj) ++nr_oj;
    for (int i = nr_oj + 1; i < T[akt].size(); ++i) T[akt][i - 1] = T[akt][i];
    T[akt].back() = oj;
    sort(T[akt].begin(), --T[akt].end(), por);
  } else
    sort(T[akt].begin(), T[akt].end(), por);
  int il_syn = T[akt].size();
  if (akt != 0) --il_syn;
  ilo[akt] = "1";
  for (int i = 0; i < il_syn; ++i) ilo[akt] = Mnoz(ilo[akt], dp[T[akt][i]]);
  dp[akt] = ilo[akt];
  vector<string> suf_dp(il_syn);
  suf_dp[il_syn - 1] = dp[T[akt][il_syn - 1]];
  for (int i = il_syn - 2; i >= 0; --i)
    suf_dp[i] = Mnoz(suf_dp[i + 1], dp[T[akt][i]]);
  string pref_ilo = "1";
  for (int wlk = 1; wlk <= il_syn; ++wlk) {
    string wyn = NaStr(wlk + 1);
    pref_ilo = Mnoz(pref_ilo, ilo[T[akt][wlk - 1]]);
    wyn = Mnoz(wyn, pref_ilo);
    if (wlk < il_syn) wyn = Mnoz(wyn, suf_dp[wlk]);
    dp[akt] = Maximum(dp[akt], wyn);
  }
  string pref_dp = "1";
  for (int i = 0; i < il_syn; ++i) {
    int akt2 = T[akt][i];
    if (i != 0) pref_dp = Mnoz(pref_dp, dp[T[akt][i - 1]]);
    int il_syn2 = T[akt2].size() - 1;
    if (il_syn2 == 0) continue;
    vector<string> suf_dp2(il_syn2);
    suf_dp2[il_syn2 - 1] = dp[T[akt2][il_syn2 - 1]];
    for (int j = il_syn2 - 2; j >= 0; --j)
      suf_dp2[j] = Mnoz(suf_dp2[j + 1], dp[T[akt2][j]]);
    string pref_ilo2 = "1";
    for (int wlk2 = 1; wlk2 <= il_syn2; ++wlk2) {
      string wyn2 = NaStr(wlk2 + 2);
      pref_ilo2 = Mnoz(pref_ilo2, ilo[T[akt2][wlk2 - 1]]);
      wyn2 = Mnoz(wyn2, pref_ilo2);
      if (wlk2 < il_syn2) wyn2 = Mnoz(wyn2, suf_dp2[wlk2]);
      wyn2 = Mnoz(wyn2, pref_dp);
      if (i + 1 < il_syn) wyn2 = Mnoz(wyn2, suf_dp[i + 1]);
      dp[akt] = Maximum(dp[akt], wyn2);
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  int n;
  cin >> n;
  if (n == 1) {
    cout << "1";
    return 0;
  }
  vector<vector<int> > T(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    T[a].push_back(b);
    T[b].push_back(a);
  }
  for (int i = 0; i < n; ++i) {
    dp.push_back("");
    ilo.push_back("");
  }
  dfs(T, 0, -1);
  cout << dp[0];
  return 0;
}
