Problem:
Score : 800 points

Problem Statement

There is a tree with N vertices. The vertices are numbered 1 through N. The i-th edge (1 \leq i \leq N - 1) connects Vertex x_i and y_i. For vertices v and w (1 \leq v, w \leq N), we will define the distance between v and w d(v, w) as "the number of edges contained in the path v-w".

A squirrel lives in each vertex of the tree. They are planning to move, as follows. First, they will freely choose a permutation of (1, 2, ..., N), p = (p_1, p_2, ..., p_N). Then, for each 1 \leq i \leq N, the squirrel that lived in Vertex i will move to Vertex p_i.

Since they like long travels, they have decided to maximize the total distance they traveled during the process. That is, they will choose p so that d(1, p_1) + d(2, p_2) + ... + d(N, p_N) will be maximized. How many such ways are there to choose p, modulo 10^9 + 7?

Constraints

2 \leq N \leq 5,000

1 \leq x_i, y_i \leq N

The input graph is a tree.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_{N - 1} y_{N - 1}

Output

Print the number of the ways to choose p so that the condition is satisfied, modulo 10^9 + 7.

Sample Input 1

3
1 2
2 3

Sample Output 1

3

The maximum possible distance traveled by squirrels is 4.
There are three choices of p that achieve it, as follows:

(2, 3, 1)

(3, 1, 2)

(3, 2, 1)

Sample Input 2

4
1 2
1 3
1 4

Sample Output 2

11

The maximum possible distance traveled by squirrels is 6.
For example, p = (2, 1, 4, 3) achieves it.

Sample Input 3

6
1 2
1 3
1 4
2 5
2 6

Sample Output 3

36

Sample Input 4

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

Sample Output 4

396

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr ll MOD = (ll)1e9 + 7LL;

class Modulo
{
public:
    Modulo(const int n, const ll mod = 1000000007LL) : m_size{n + 1}, m_mod{mod}  // mod should be prime
    {
        assert(n > 0);
        m_fact.resize(n + 1);
        m_inv.resize(n + 1);
        m_inv_fact.resize(n + 1);
        m_fact[0] = 1;
        m_inv[0] = 1;
        m_inv_fact[0] = 1;
        m_fact[1] = 1;
        m_inv[1] = 1;
        m_inv_fact[1] = 1;
        for (int i = 2; i <= n; i++) {
            m_fact[i] = (m_fact[i - 1] * static_cast<ll>(i)) % mod;
            m_inv[i] = ((mod - (mod / static_cast<ll>(i))) * m_inv[static_cast<unsigned int>(mod) % i]) % mod;
            m_inv_fact[i] = (m_inv_fact[i - 1] * m_inv[i]) % mod;
        }
    }

    ll factorial(const int n) const
    {
        assert(n < m_size);
        return m_fact[n];
    }

    ll inverse(const int n) const
    {
        assert(n < m_size);
        return m_inv[n];
    }

    ll inverseFactorial(const int n) const
    {
        assert(n < m_size);
        return m_inv_fact[n];
    }

    ll permutation(const int n, const int k) const
    {
        assert(n < m_size);
        assert(k <= n);
        return (m_fact[n] * m_inv_fact[n - k]) % m_mod;
    }

    ll combination(const int n, const int k) const
    {
        assert(n < m_size);
        assert(k <= n);
        return (((m_fact[n] * m_inv_fact[k]) % m_mod) * m_inv_fact[n - k]) % m_mod;
    }

    ll homogenious(const int n, const int k) const
    {
        if (n == 0 and k == 0) {
            return 1;
        }
        return combination(n + k - 1, k);
    }

private:
    const int m_size;
    const ll m_mod;
    vector<ll> m_fact;
    vector<ll> m_inv;
    vector<ll> m_inv_fact;
};


struct Graph {
    Graph(const int n)
    {
        edge.resize(n);
    }
    void addEdge(const int from, const int to)
    {
        edge[from].push_back(to);
    }
    vector<vector<int>> edge;
};

int dfs(const Graph& g, const int s, vector<int>& sub)
{
    int maxi = 0;
    sub[s] = 1;
    for (const int to : g.edge[s]) {
        if (sub[to] == 0) {
            dfs(g, to, sub);
            maxi = max(maxi, sub[to]);
            sub[s] += sub[to];
        }
    }
    return maxi;
}

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

    int N;
    cin >> N;
    Graph g(N);
    for (int i = 0; i < N - 1; i++) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        g.addEdge(u, v);
        g.addEdge(v, u);
    }
    vector<int> sub(N, 0);
    vector<int> num(N, 0);
    for (int i = 0; i < N; i++) {
        fill(sub.begin(), sub.end(), 0);
        num[i] = dfs(g, i, sub);
    }
    const int root = min_element(num.begin(), num.end()) - num.begin();
    const int maxi = num[root];
    int cnt = 0;
    for (int i = 0; i < N; i++) {
        if (num[i] == maxi) {
            cnt++;
        }
    }
    Modulo mod(N + 1);
    if (cnt == 2) {
        const ll ans = mod.factorial(N / 2);
        cout << (ans * ans) % MOD << endl;
        return 0;
    } else {
        fill(sub.begin(), sub.end(), 0);
        dfs(g, root, sub);
        vector<int> nums;
        for (const int to : g.edge[root]) {
            nums.push_back(sub[to]);
        }
        const int size = nums.size();
        vector<vector<ll>> dp(size, vector<ll>(N, 0));
        auto get = [&](const int i, const int j) {
            return (((mod.combination(nums[i], j) * mod.combination(nums[i], j)) % MOD) * mod.factorial(j)) % MOD;
        };
        for (int i = 0; i <= nums[0]; i++) {
            dp[0][i] = get(0, i);
        }
        for (int i = 1; i < size; i++) {
            for (int k = 0; k <= nums[i]; k++) {
                for (int j = k; j < N; j++) {
                    dp[i][j] += (dp[i - 1][j - k] * get(i, k)) % MOD;
                    dp[i][j] %= MOD;
                }
            }
        }
        ll ans = 0;
        for (int i = 0; i < N; i++) {
            const ll add = (mod.factorial(N - i) * dp[size - 1][i]) % MOD;
            ans += (i % 2 == 0 ? add : MOD - add);
            ans %= MOD;
        }
        cout << ans << endl;
    }
    return 0;
}