#define _USE_MATH_DEFINES
#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <complex>
#include <string>
#include <vector>
#include <array>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
#include <iterator>
using namespace std;

// modを法としたときの逆数を求める
void mod_inverse(int n, vector<long long>& inv, int mod)
{
    inv.assign(n+1, -1);
    inv[1] = 1;
    for(int i=2; i<=n; ++i)
        inv[i] = inv[mod % i] * (mod - mod / i) % mod;
}

// 階乗数の事前計算を用いた各種組合せ
class FactorialCalculation
{
private:
    const int mod;
    vector<long long> factorial;
    vector<long long> invFactorial;
public:
    FactorialCalculation(int n, int mod) : mod(mod)
    {
        factorial.resize(n+1, 1);
        invFactorial.resize(n+1, 1);
        vector<long long> inv;
        mod_inverse(n, inv, mod);
        for(int i=1; i<=n; ++i){
            factorial[i] = factorial[i-1] * i % mod;
            invFactorial[i] = invFactorial[i-1] * inv[i] % mod;
        }
    }
    long long getFactorial(int n){
        return factorial[n];
    }
    long long getInvFactorial(int n){
        return invFactorial[n];
    }
    long long getPermutation(int n, int r){
        if(n < r)
            return 0;
        return factorial[n] * invFactorial[n-r] % mod;
    }
    long long getCombination(int n, int r){
        if(n < r)
            return 0;
        return getPermutation(n, r) * invFactorial[r] % mod;
    }
    long long getHomogeneous(int n, int r){
        return getCombination(n+r-1, r);
    }
};

// 木の重心
int treeCentroid(const vector<vector<int> >& edges, vector<int>& centroid, int curr = 0, int prev = -1)
{
    int n = edges.size();
    int sum = 0;
    bool ok = true;
    for(int next : edges[curr]){
        if(next == prev)
            continue;
        int size = treeCentroid(edges, centroid, next, curr);
        sum += size;
        if(size > n / 2)
            ok = false;
    }

    if(ok && n - 1 - sum <= n / 2)
        centroid.push_back(curr);
    return sum + 1;
}

const int MOD = 1000000007;

int countSubTreeSize(const vector<vector<int> >& edges, int curr, int prev)
{
    int ans = 1;
    for(int next : edges[curr]){
        if(next == prev)
            continue;
        ans += countSubTreeSize(edges, next, curr);
    }
    return ans;
}

long long solve(const vector<vector<int> >& edges)
{
    int n = edges.size();
    FactorialCalculation fc(n, MOD);

    vector<int> centroid;
    treeCentroid(edges, centroid);
    if(centroid.size() == 2){
        long long ans = fc.getFactorial(n/2);
        ans *= ans;
        ans %= MOD;
        return ans;
    }

    vector<long long> dp(n, 0);
    dp[0] = 1;
    for(int node : edges[centroid[0]]){
        int cnt = countSubTreeSize(edges, node, centroid[0]);
        for(int i=n-1; i>=0; --i){
            for(int j=1; j<=cnt && i+j<n; ++j){
                long long tmp = fc.getCombination(cnt, j) * fc.getPermutation(cnt, j);
                tmp %= MOD;
                dp[i+j] += dp[i] * tmp;
                dp[i+j] %= MOD;
            }
        }
    }

    long long ans = fc.getFactorial(n);
    for(int i=1; i<n; ++i){
        long long tmp = dp[i] * fc.getFactorial(n - i);
        tmp %= MOD;
        if(i % 2 == 0)
            ans += tmp;
        else
            ans += MOD - tmp;
        ans %= MOD;
    }
    return ans;
}

int main()
{
    int n;
    cin >> n;
    vector<vector<int> > edges(n);
    for(int i=0; i<n-1; ++i){
        int x, y;
        cin >> x >> y;
        -- x;
        -- y;
        edges[x].push_back(y);
        edges[y].push_back(x);
    }

    cout << solve(edges) << endl;

    return 0;
}


Measured memory_bytes: 1024