#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target( \
    "sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
using namespace std;
template <typename T1, typename T2>
void ckmin(T1 &a, T2 b) {
  if (a > b) a = b;
}
template <typename T1, typename T2>
void ckmax(T1 &a, T2 b) {
  if (a < b) a = b;
}
int read() {
  int x = 0, f = 0;
  char ch = getchar();
  while (!isdigit(ch)) f |= ch == '-', ch = getchar();
  while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
  return f ? -x : x;
}
template <typename T>
void print(T x) {
  if (x < 0) putchar('-'), x = -x;
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}
template <typename T>
void print(T x, char let) {
  print(x), putchar(let);
}
const int mlen = 1 << 20;
const int N = mlen + 5;
const int mod = 998244353;
unsigned long long omgs[N];
int rev[N];
int qpow(int a, int b = mod - 2) {
  int res = 1;
  while (b) {
    if (b & 1) res = 1ll * res * a % mod;
    a = 1ll * a * a % mod;
    b >>= 1;
  }
  return res;
}
const int G = qpow(3, (mod - 1) / mlen);
void setup() {
  omgs[mlen / 2] = 1;
  for (int i = mlen / 2 + 1; i < mlen; i++) omgs[i] = G * omgs[i - 1] % mod;
  for (int i = mlen / 2 - 1; i > 0; i--) omgs[i] = omgs[i << 1];
}
int getR(int len) {
  int lim = 1, L = 0;
  while (lim <= len) lim <<= 1, L++;
  for (int i = 0; i < lim; i++)
    rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << L - 1);
  return lim;
}
inline void dft(vector<int> &a, int lim) {
  a.resize(lim);
  static unsigned long long A[N];
  for (int i = 0; i < lim; i++) A[rev[i]] = a[i];
  for (int mid = 1; mid < lim; mid <<= 1) {
    for (int i = 0; i < lim; i += mid << 1) {
      unsigned long long *W = omgs + mid;
      for (int j = 0; j < mid; j++) {
        unsigned long long tmp = *(W++) * A[i + j + mid] % mod;
        A[i + j + mid] = A[i + j] + mod - tmp;
        A[i + j] += tmp;
      }
    }
  }
  for (int i = 0; i < lim; i++) a[i] = A[i] % mod;
}
inline void idft(vector<int> &a, int lim) {
  a.resize(lim);
  dft(a, lim), reverse(a.begin() + 1, a.end());
  int linv = mod - (mod - 1) / lim;
  for (int i = 0; i < lim; i++) a[i] = 1ll * a[i] * linv % mod;
}
vector<int> operator*(vector<int> a, vector<int> b) {
  int len = (int(a.size())) + (int(b.size())) - 1, lim = getR(len);
  dft(a, lim), dft(b, lim);
  for (int i = 0; i < lim; i++) a[i] = 1ll * a[i] * b[i] % mod;
  idft(a, lim), a.resize(len);
  return a;
}
vector<int> adj[N];
int n;
int son[N];
void dfs1(int u, int fa) {
  for (auto v : adj[u]) {
    if (v == fa) continue;
    son[u]++;
    dfs1(v, u);
  }
}
int fac[N], ifac[N];
inline int C(int n, int m) {
  return 1ll * fac[n] * ifac[n - m] % mod * ifac[m] % mod;
}
int main() {
  setup();
  n = read();
  fac[0] = 1;
  for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % mod;
  ifac[n] = qpow(fac[n]);
  for (int i = n; i >= 1; i--) ifac[i - 1] = 1ll * ifac[i] * i % mod;
  for (int i = 1; i <= n - 1; i++) {
    int u = read(), v = read();
    adj[u].push_back(v), adj[v].push_back(u);
  }
  dfs1(1, 0);
  vector<int> f = {1};
  sort(son + 1, son + n + 1, greater<int>());
  for (int i = 1; i <= n; i++) {
    int j = i;
    while (j < n && son[i] == son[j + 1]) j++;
    int up = j - i + 1;
    vector<int> g(up + 1);
    int cf = 1;
    for (int i = 0; i <= up; i++) {
      int coef = 1ll * C(up, i) * cf % mod;
      g[i] = coef;
      cf = 1ll * cf * (mod - son[j]) % mod;
    }
    f = f * g;
    i = j;
  }
  int ans = 0;
  for (int i = 0; i <= n - 1; i++) ans = (ans + 1ll * fac[n - i] * f[i]) % mod;
  print(ans, '\n');
  return 0;
}
