#[allow(unused_imports)]
use std::cmp::{min,max};
#[allow(unused_imports)]
use std::collections::BTreeMap;

fn main() {
    let n = read_i64() as usize;
    let edges = {
        let mut res = vec![];
        for _ in 0..n-1 {
            let xs = read_vec_i64();
            res.push((xs[0]-1,xs[1]-1));
        }
        res
    };
    let mut res_h = 1000;
    let mut res_leaf = (1 as i64) << 61;
    // single top
    for i in 0..n {
        let mut xs: Vec<i64> = vec![-1; n];
        let mut ys = vec![0; n];
        xs[i] = 1;
        let mut h = 1;
        for _ in 0..n {
            for k in 0..n-1 {
                let a = edges[k].0 as usize;
                let b = edges[k].1 as usize;
                if xs[a] == -1 && xs[b] != -1 {
                    xs[a] = xs[b] + 1;
                    ys[b] += 1;
                    h = max(h, xs[a]);
                }
                if xs[a] != -1 && xs[b] == -1 {
                    xs[b] = xs[a] + 1;
                    ys[a] += 1;
                    h = max(h, xs[b]);
                }
            }
        }
        let mut zs = vec![1; 101];
        for k in 0..n {
            zs[xs[k] as usize] = max(zs[xs[k] as usize], ys[k]);
        }
        let leaf = zs.iter().fold(1, |x,y| x * y);
        if h < res_h {
            res_h = h;
            res_leaf = leaf;
        }
        if h == res_h && leaf < res_leaf {
            res_leaf = leaf;
        }
    }
    // double top
    for i in 0..n-1 {
        let mut xs: Vec<i64> = vec![-1; n];
        let mut ys = vec![0; n];
        xs[edges[i].0 as usize] = 1;
        xs[edges[i].1 as usize] = 1;
        let mut h = 1;
        for _ in 0..n {
            for k in 0..n-1 {
                let a = edges[k].0 as usize;
                let b = edges[k].1 as usize;
                if xs[a] == -1 && xs[b] != -1 {
                    xs[a] = xs[b] + 1;
                    ys[b] += 1;
                    h = max(h, xs[a]);
                }
                if xs[a] != -1 && xs[b] == -1 {
                    xs[b] = xs[a] + 1;
                    ys[a] += 1;
                    h = max(h, xs[b]);
                }
            }
        }
        let mut zs = vec![1; 101];
        for k in 0..n {
            zs[xs[k] as usize] = max(zs[xs[k] as usize], ys[k]);
        }
        let leaf = 2 * zs.iter().fold(1, |x,y| x * y);
        //println!("i={}, h={}, leaf={}", i, h, leaf);
        if h < res_h {
            res_h = h;
            res_leaf = leaf;
        }
        if h == res_h && leaf < res_leaf {
            res_leaf = leaf;
        }
    }

    println!("{} {}", res_h, res_leaf);
}

#[allow(dead_code)]
fn read_line() -> String {
    let mut ret = String::new();
    std::io::stdin().read_line(&mut ret).ok();
    ret.pop();
    return ret;
}

#[allow(dead_code)]
fn read_i64() -> i64 {
    let ss = read_line();
    return ss.parse::<i64>().unwrap();
}

#[allow(dead_code)]
fn read_vec_i64() -> Vec<i64> {
    let mut res = vec![];
    let ss = read_line();
    for ts in ss.split_whitespace() {
        let x = ts.parse::<i64>().unwrap();
        res.push(x);
    }
    return res;
}

use std::fmt::Display;
#[allow(dead_code)]
fn write_vec_i64<T: Display>(xs: &Vec<T>) {
    if xs.len() == 0 {
        println!("");
        return;
    }
    print!("{}", xs[0]);
    for i in 1..xs.len() {
        print!(" {}", xs[i]);
    }
    println!("");
}


Measured memory_bytes: 4476