use std::cmp;
// use std::collections::HashMap;
// use std::collections::HashSet;
use std::collections::VecDeque;


// const INF: i64 = 1_000_000_000;



// fn solve_v(g: &Vec<Vec<usize> >, v: usize) -> i64 {
//     return 0;
// }
fn solve(g: &Vec<Vec<usize> >, vs: Vec<usize>) -> usize {
    let n = g.len();
    let mut d = vec![n; n];
    let mut q = VecDeque::new();
    let mut b = Vec::new();
    for &v in vs.iter() {
        q.push_back(v);
        d[v] = 0;
    }
    while !q.is_empty() {
        let v = q.pop_front().unwrap();
        let mut cnt = 0;
        for &w in g[v].iter() {
            if d[w] < n {
                continue;
            }
            cnt += 1;
            d[w] = d[v] + 1;
            q.push_back(w);
        }
        if b.len() == d[v] {
            b.push(cnt);
        } else {
            b[d[v]] = cmp::max(b[d[v]], cnt);
        }
    }
    let mut ret: usize = vs.len();
    // println!("{:?}", b);
    b.pop();
    for &cnt in b.iter() {
        ret *= cnt;
    }
    return ret;
}


fn main() {
    let cin = stdin();
    let cin = cin.lock();
    let mut sc = Scanner::new(cin);
    let n = sc.read();
    let mut g = vec![vec![]; n];
    for _ in 0..n-1 {
        let a = sc.read::<usize>() - 1;
        let b = sc.read::<usize>() - 1;
        g[a].push(b);
        g[b].push(a);
    }
    let mut start = 0;
    let mut parents;
    let mut goal = n;
    {  // bfs
        parents = vec![n; n];
        let mut q = VecDeque::new();
        q.push_back(start);
        parents[start] = start;
        while !q.is_empty() {
            let v = q.pop_front().unwrap();
            for &w in g[v].iter() {
                if parents[w] < n {
                    continue;
                }
                parents[w] = v;
                q.push_back(w);
                goal = w;
            }
        }
    }
    start = goal;
    {  // bfs
        parents = vec![n; n];
        let mut q = VecDeque::new();
        q.push_back(start);
        parents[start] = start;
        while !q.is_empty() {
            let v = q.pop_front().unwrap();
            for &w in g[v].iter() {
                if parents[w] < n {
                    continue;
                }
                parents[w] = v;
                q.push_back(w);
                goal = w;
            }
        }
    }
    let mut path = Vec::new();
    while goal != start {
        path.push(goal);
        goal = parents[goal];
    }
    let d = path.len();
    path.push(start);
    // println!("{:?}", g);
    // println!("{:?}", parents);
    // println!("{:?}", path);
    // println!("{:?}", d);

    let mut cands = Vec::new();
    if d%2 == 0 {
        let v = path[d/2];
        cands.push(solve(&g, vec![v]));
        for &w in g[v].iter() {
            cands.push(solve(&g, vec![v, w]));
        }
    } else {
        cands.push(solve(&g, vec![path[d/2], path[(d+1)/2]]));
    }
    let ans0 = d/2 + 1;
    let ans1 = cands.iter().min().unwrap();
    println!("{} {}", ans0, ans1);
}

// thanks, ir5
use std::io::{stdin, Read, StdinLock};
use std::str::FromStr;

struct Scanner<'a> {
    cin: StdinLock<'a>,
}

impl<'a> Scanner<'a> {
    fn new(cin: StdinLock<'a>) -> Scanner<'a> {
        Scanner { cin: cin }
    }

    fn read1<T: FromStr>(&mut self) -> Option<T> {
        let token = self.cin
            .by_ref()
            .bytes()
            .map(|c| c.unwrap() as char)
            .skip_while(|c| c.is_whitespace())
            .take_while(|c| !c.is_whitespace())
            .collect::<String>();
        token.parse::<T>().ok()
    }

    fn read<T: FromStr>(&mut self) -> T {
        self.read1().unwrap()
    }
}


Measured memory_bytes: 4476