use proconio::{input, marker::Usize1};
// modint {{{
#[allow(dead_code)]
mod modint {
    use std::{
        cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
        fmt::{Debug, Display},
        iter::{Product, Sum},
        mem::swap,
        ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
    };

    pub type ModValue = i64;

    #[derive(Debug, Clone, Copy)]
    struct Rational {
        num: ModValue,
        den: ModValue,
    }

    #[allow(clippy::many_single_char_names)]
    fn red(r: i64, p: i64) -> (i64, i64, i64) {
        if r.abs() <= 10000 {
            return (r, 1, 0);
        }
        let mut nxt_r = p % r;
        let mut q = p / r;
        if 2 * nxt_r >= r {
            nxt_r -= r;
            q += 1;
        }
        if 2 * nxt_r <= -r {
            nxt_r += r;
            q -= 1;
        }
        let (x, z, y) = red(nxt_r, r);
        (x, y - q * z, z)
    }

    #[derive(Clone, Copy)]
    pub struct Mint<Mod: ModTrait>(ModValue, std::marker::PhantomData<Mod>);

    impl<Mod: ModTrait> Mint<Mod> {
        fn from_value_unchecked(value: ModValue) -> Self {
            Self(value, std::marker::PhantomData)
        }
        fn normalize(value: ModValue) -> ModValue {
            let value = value % Mod::modulus();
            if 0 <= value {
                value
            } else {
                value + Mod::modulus()
            }
        }
        fn guess(&self) -> Rational {
            let (mut num, mut den, _) = red(self.0, Mod::modulus());
            if den < 0 {
                num = -num;
                den = -den;
            }
            Rational { num, den }
        }
        pub fn from_i64(value: ModValue) -> Self {
            Self::from_value_unchecked(Self::normalize(value))
        }
        pub fn from_frac(num: ModValue, den: ModValue) -> Self {
            Self::from_i64(num) / Self::from_i64(den)
        }
        pub fn zero() -> Self {
            Self::from_value_unchecked(0)
        }
        pub fn one() -> Self {
            Self::from_value_unchecked(1)
        }
        #[allow(clippy::many_single_char_names)]
        pub fn inv(self) -> Self {
            assert_ne!(
                self,
                Self::zero(),
                "attempted to take the inverse of zero mint"
            );
            let mut x = self.0;
            let mut y = Mod::modulus();
            let mut u = 1;
            let mut v = 0;
            while x != 0 {
                let q = y / x;
                y -= q * x;
                v -= q * u;
                swap(&mut x, &mut y);
                swap(&mut u, &mut v);
            }
            assert!(x == 0 && y == 1 && u.abs() == Mod::modulus() && v.abs() < Mod::modulus());
            Self::from_value_unchecked(if v < 0 { v + Mod::modulus() } else { v })
        }
        pub fn pow(mut self, mut p: u64) -> Self {
            let mut ans = Self::one();
            while 0 != p {
                if p % 2 == 1 {
                    ans *= self;
                }
                self *= self;
                p /= 2;
            }
            ans
        }
        pub fn from_pow(a: ModValue, p: u64) -> Self {
            Self::from_i64(a).pow(p)
        }
    }

    impl<Mod: ModTrait> Debug for Mint<Mod> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
            let Rational { num, den } = self.guess();
            f.debug_tuple("Mint")
                .field(&if den == 1 {
                    num.to_string()
                } else {
                    format!("{}/{}", num, den)
                })
                .finish()
        }
    }

    impl<Mod: ModTrait> Display for Mint<Mod> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
            write!(f, "{}", self.0)
        }
    }

    macro_rules! forward_ref_binop {
        ($(impl $imp:ident, $method:ident)*) => {
            $(
                impl<'a, Mod: ModTrait> $imp<Mint<Mod>> for &'a Mint<Mod> {
                    type Output = Mint<Mod>;

                    #[inline]
                    fn $method(self, other: Mint<Mod>) -> Self::Output {
                        $imp::$method(*self, other)
                    }
                }

                impl<'a, Mod: ModTrait> $imp<&'a Mint<Mod>> for Mint<Mod> {
                    type Output = Mint<Mod>;

                    #[inline]
                    fn $method(self, other: &Mint<Mod>) -> Self::Output {
                        $imp::$method(self, *other)
                    }
                }

                impl<'a, Mod: ModTrait> $imp<&'a Mint<Mod>> for &'a Mint<Mod> {
                    type Output = Mint<Mod>;

                    #[inline]
                    fn $method(self, other: &Mint<Mod>) -> Self::Output {
                        $imp::$method(*self, *other)
                    }
                }
            )*
        };
    }

    macro_rules! forward_ref_op_assign {
        ($(impl $imp:ident, $method:ident)*) => {
            $(
                impl<'a, Mod: ModTrait> $imp<&Mint<Mod>> for Mint<Mod> {
                    #[inline]
                    fn $method(&mut self, other: &Mint<Mod>) {
                        $imp::$method(self, *other);
                    }
                }
            )*
        }
    }

    #[allow(clippy::suspicious_arithmetic_impl)]
    impl<Mod: ModTrait> Add for Mint<Mod> {
        type Output = Self;

        #[inline]
        fn add(self, rhs: Self) -> Self {
            let value = self.0 + rhs.0;
            Self::from_value_unchecked(if value < Mod::modulus() {
                value
            } else {
                value - Mod::modulus()
            })
        }
    }

    #[allow(clippy::suspicious_arithmetic_impl)]
    impl<Mod: ModTrait> Sub for Mint<Mod> {
        type Output = Self;

        #[inline]
        fn sub(self, rhs: Self) -> Self {
            let value = self.0 - rhs.0;
            Self::from_value_unchecked(if 0 <= value {
                value
            } else {
                value + Mod::modulus()
            })
        }
    }

    #[allow(clippy::suspicious_arithmetic_impl)]
    impl<Mod: ModTrait> Mul for Mint<Mod> {
        type Output = Self;

        #[inline]
        fn mul(self, rhs: Self) -> Self {
            Self::from_value_unchecked(self.0 * rhs.0 % Mod::modulus())
        }
    }

    #[allow(clippy::suspicious_arithmetic_impl)]
    impl<Mod: ModTrait> Div for Mint<Mod> {
        type Output = Self;

        #[inline]
        fn div(self, rhs: Self) -> Self {
            self * rhs.inv()
        }
    }

    impl<Mod: ModTrait> Neg for Mint<Mod> {
        type Output = Self;

        #[inline]
        fn neg(self) -> Self {
            if self.0 == 0 {
                Self::zero()
            } else {
                Self::from_value_unchecked(Mod::modulus() - self.0)
            }
        }
    }

    impl<Mod: ModTrait> Neg for &Mint<Mod> {
        type Output = Mint<Mod>;

        #[inline]
        fn neg(self) -> Self::Output {
            (*self).neg()
        }
    }

    macro_rules! forward_assign_biop {
        ($(impl $trait: ident, $fn_assign: ident, $fn: ident)*) => {
            $(
                impl<Mod: ModTrait> $trait for Mint<Mod> {
                    #[inline]
                    fn $fn_assign(&mut self, rhs: Self) {
                        *self = self.$fn(rhs);
                    }
                }
            )*
        };
    }

    forward_assign_biop! {
        impl AddAssign, add_assign, add
        impl SubAssign, sub_assign, sub
        impl MulAssign, mul_assign, mul
        impl DivAssign, div_assign, div
    }

    forward_ref_binop! {
        impl Add, add
        impl Sub, sub
        impl Mul, mul
        impl Div, div
    }

    forward_ref_op_assign! {
        impl AddAssign, add_assign
        impl SubAssign, sub_assign
        impl MulAssign, mul_assign
        impl DivAssign, div_assign
    }

    impl<Mod: ModTrait> PartialEq for Mint<Mod> {
        fn eq(&self, other: &Self) -> bool {
            self.0 == other.0
        }
    }
    impl<Mod: ModTrait> Eq for Mint<Mod> {}
    impl<Mod: ModTrait> Ord for Mint<Mod> {
        fn cmp(&self, other: &Self) -> Ordering {
            self.0.cmp(&other.0)
        }
    }
    impl<Mod: ModTrait> PartialOrd for Mint<Mod> {
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl<Mod: ModTrait> From<ModValue> for Mint<Mod> {
        fn from(value: ModValue) -> Self {
            Self::from_i64(value)
        }
    }

    impl<Mod: ModTrait> From<Mint<Mod>> for ModValue {
        fn from(mint: Mint<Mod>) -> Self {
            mint.0
        }
    }

    impl<Mod: ModTrait> Sum for Mint<Mod> {
        fn sum<I>(iter: I) -> Self
        where
            I: Iterator<Item = Self>,
        {
            iter.fold(Self::zero(), Add::add)
        }
    }
    impl<'a, Mod: 'a + ModTrait> Sum<&'a Self> for Mint<Mod> {
        fn sum<I>(iter: I) -> Self
        where
            I: Iterator<Item = &'a Self>,
        {
            iter.fold(Self::zero(), Add::add)
        }
    }
    impl<Mod: ModTrait> Product for Mint<Mod> {
        fn product<I>(iter: I) -> Self
        where
            I: Iterator<Item = Self>,
        {
            iter.fold(Self::one(), Mul::mul)
        }
    }
    impl<'a, Mod: 'a + ModTrait> Product<&'a Self> for Mint<Mod> {
        fn product<I>(iter: I) -> Self
        where
            I: Iterator<Item = &'a Self>,
        {
            iter.fold(Self::one(), Mul::mul)
        }
    }

    #[macro_export]
    macro_rules! mint {
        ($value: expr) => {
            Mint::from_i64($value)
        };
    }

    #[macro_export]
    macro_rules! from_frac {
        ($num: expr, $den: expr) => {
            Mint::from_frac($num, $den)
        };
    }

    #[macro_export]
    macro_rules! from_pow {
        ($a: expr, $b: expr) => {
            Mint::from_pow($a, $b)
        };
    }

    pub trait ModTrait: Clone + Copy + Debug {
        fn modulus() -> ModValue;
    }

    #[derive(Debug, Clone)]
    pub struct Factorial<Mod: ModTrait> {
        normal: Vec<Mint<Mod>>,
        inverse: Vec<Mint<Mod>>,
    }

    impl<Mod: ModTrait> Factorial<Mod> {
        pub fn is_empty(&self) -> bool {
            self.normal.is_empty()
        }
        pub fn len(&self) -> usize {
            self.normal.len()
        }
        pub fn with_len(len: usize) -> Self {
            if len == 0 {
                Self {
                    normal: Vec::new(),
                    inverse: Vec::new(),
                }
            } else {
                let mut normal = vec![Mint::one(); len];
                for i in 1..len {
                    normal[i] = normal[i - 1] * Mint::from_i64(i as i64);
                }
                let mut inverse = vec![normal.last().unwrap().inv(); len];
                for i in (1..len).rev() {
                    inverse[i - 1] = inverse[i] * Mint::from_i64(i as i64);
                }
                Self { normal, inverse }
            }
        }
        pub fn inv(&self, i: usize) -> Mint<Mod> {
            self.inverse[i]
        }
        pub fn falling(&self, n: usize, p: usize) -> Mint<Mod> {
            if p == 0 {
                Mint::one()
            } else if n < p {
                Mint::zero()
            } else {
                self[n] * self.inv(n - p)
            }
        }
        pub fn binom(&self, n: usize, k: usize) -> Mint<Mod> {
            if k == 0 {
                Mint::one()
            } else if n < k {
                Mint::zero()
            } else {
                self[n] * self.inv(n - k) * self.inv(k)
            }
        }
    }

    impl<Mod: ModTrait, I: std::slice::SliceIndex<[Mint<Mod>]>> std::ops::Index<I> for Factorial<Mod> {
        type Output = I::Output;

        #[inline]
        fn index(&self, index: I) -> &Self::Output {
            &self.normal[index]
        }
    }

    #[derive(Clone, Copy, Debug)]
    pub struct Mod100000007 {}
    #[derive(Clone, Copy, Debug)]
    pub struct Mod998244353 {}
    impl ModTrait for Mod100000007 {
        fn modulus() -> ModValue {
            1_000_000_007
        }
    }
    impl ModTrait for Mod998244353 {
        fn modulus() -> ModValue {
            998_244_353
        }
    }
    pub type Mint100000007 = Mint<Mod100000007>;

    pub type Mint998244353 = Mint<Mod998244353>;
}
// }}}
type Mint = modint::Mint100000007;
type Factorial = modint::Factorial<modint::Mod100000007>;

fn mul(a: &[Mint], b: &[Mint]) -> Vec<Mint> {
    let mut c = vec![Mint::zero(); a.len() + b.len() - 1];
    for i in 0..a.len() {
        for j in 0..b.len() {
            c[i + j] += a[i] * b[j];
        }
    }
    c
}

fn poly(d: usize, fact: &Factorial) -> Vec<Mint> {
    (0..=d)
        .map(|i| fact.binom(d, i) * fact.falling(d, i))
        .collect()
}

fn perfect(a: &[usize], fact: &Factorial) -> Mint {
    let sum = a.iter().sum::<usize>();
    let mut ans = vec![Mint::one()];
    for &d in a {
        let mut swp = mul(&ans, &poly(d, &fact));
        ans = std::mem::take(&mut swp);
    }
    ans.iter()
        .enumerate()
        .map(|(i, &x)| {
            let y = x * fact[sum - i];
            match i % 2 {
                0 => y,
                1 => -y,
                _ => panic!(),
            }
        })
        .sum::<Mint>()
}

fn cal(branch_sizes: &[usize], fact: &Factorial) -> Mint {
    perfect(
        std::iter::once(1)
            .chain(branch_sizes.iter().copied())
            .collect::<Vec<_>>()
            .as_slice(),
        fact,
    ) + perfect(branch_sizes, fact)
}

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum Centroid {
    Vertex(usize),
    Edge(usize, usize),
}

fn centoroid(g: &[Vec<usize>]) -> (Centroid, Vec<usize>) {
    let mut ans = None;
    let mut size = vec![0; g.len()];
    fn dfs(
        x: usize,
        p: usize,
        g: &[Vec<usize>],
        ans: &mut Option<Centroid>,
        size: &mut [usize],
    ) -> usize {
        let mut sx = 1;
        for y in g[x].iter().copied().filter(|&y| y != p) {
            sx += dfs(y, x, g, ans, size);
        }
        if g.len() <= sx * 2 {
            ans.get_or_insert_with(|| {
                if g.len() == sx * 2 {
                    Centroid::Edge(x, p)
                } else {
                    Centroid::Vertex(x)
                }
            });
        }
        size[x] = sx;
        sx
    }
    dfs(0, 0, &g, &mut ans, &mut size);
    (ans.unwrap(), size)
}

fn main() {
    input!(n: usize, uv: [(Usize1, Usize1); n - 1]);
    let mut g = vec![vec![]; n];
    for (u, v) in uv {
        g[u].push(v);
        g[v].push(u);
    }
    let fact = Factorial::with_len(n * n + 1);
    println!(
        "{}",
        match centoroid(&g) {
            (Centroid::Vertex(x), size) => {
                cal(
                    &g[x]
                        .iter()
                        .filter_map(|&y| {
                            if n <= 2 * size[y] {
                                None
                            } else {
                                Some(size[y])
                            }
                        })
                        .chain(std::iter::once(n - size[x]))
                        .collect::<Vec<_>>(),
                    &fact,
                )
            }
            (Centroid::Edge(_, _), _) => {
                fact[n / 2] * fact[n / 2]
            }
        }
    );
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_f() {
        let fact = Factorial::with_len(300);
        assert_eq!(
            poly(0, &fact),
            [1].iter().copied().map(Mint::from_i64).collect::<Vec<_>>()
        );
        assert_eq!(
            poly(1, &fact),
            [1, 1]
                .iter()
                .copied()
                .map(Mint::from_i64)
                .collect::<Vec<_>>()
        );
        assert_eq!(
            poly(2, &fact),
            [1, 4, 2]
                .iter()
                .copied()
                .map(Mint::from_i64)
                .collect::<Vec<_>>()
        );
        assert_eq!(
            poly(3, &fact),
            [1, 9, 18, 6]
                .iter()
                .copied()
                .map(Mint::from_i64)
                .collect::<Vec<_>>()
        );
    }

    #[test]
    fn test_perfect() {
        let fact = Factorial::with_len(300);
        assert_eq!(perfect(&[0], &fact), mint!(1));
        assert_eq!(perfect(&[1], &fact), mint!(0));
        assert_eq!(perfect(&[2], &fact), mint!(0));
        assert_eq!(perfect(&[1, 1], &fact), mint!(1));
        assert_eq!(perfect(&[1, 1, 1], &fact), mint!(2));
        assert_eq!(perfect(&[1, 1, 1, 1], &fact), mint!(9));
    }

    #[test]
    fn test_cal() {
        let fact = Factorial::with_len(300);
        assert_eq!(cal(&[1, 1], &fact), mint!(3));
        assert_eq!(cal(&[1, 1, 1], &fact), mint!(11));
        assert_eq!(cal(&[1, 2, 3], &fact), mint!(396));
    }

    #[test]
    fn test_centroid() {
        assert_eq!(centoroid(&[Vec::new()]).0, Centroid::Vertex(0));
        assert_eq!(centoroid(&[vec![1], vec![0]]).0, Centroid::Edge(1, 0));
        assert_eq!(
            centoroid(&[vec![1], vec![0, 2], vec![1]]).0,
            Centroid::Vertex(1)
        );
        assert_eq!(
            centoroid(&[vec![1, 2, 3], vec![0], vec![0], vec![0]]).0,
            Centroid::Vertex(0)
        );
        assert_eq!(
            centoroid(&[
                vec![1, 2, 3],
                vec![0],
                vec![0],
                vec![0, 4, 5],
                vec![3],
                vec![3]
            ])
            .0,
            Centroid::Edge(3, 0),
        );
    }
}


Measured memory_bytes: 393500