#include <bits/stdc++.h>
#define int long long
#define P(x) {if (debug) cout << x << endl;}
#define H(x) P(#x << ": " << (x))
#define FR(i,a,b) for (int i=(a); i<(b); i++)
#define F(i,n) FR(i,0,n)
#define DR(i,a,b) for (int i=(b); i-->(a);)
#define D(i,n) DR(i,0,n)
#define S(s) (int)(s).size()
#define ALL(v) v.begin(), v.end()
#define MI(a,v) a = min(a,v)
#define MA(a,v) a = max(a,v)
#define V vector
#define pb push_back
#define mt make_tuple
using namespace std;
template<class T> ostream &operator<<(ostream &os, V<T> v) {
    F(i,S(v)) os<<(i?" ":"")<<v[i];
    return os;
}
const bool debug = 1;
const int INF = 9e18;

V<int> w;
V<V<int>> g;
void dfs(int u, int par, int d) {
    MA(w[d], S(g[u]) - (par != -1));
    for (int v : g[u]) if (v != par)
        dfs(v, u, d+1);
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int n; cin>>n;
    g.resize(n);
    F(_,n-1) {
        int a,b; cin>>a>>b;
        a--, b--;
        g[a].pb(b);
        g[b].pb(a);
    }
    int best = INF, leafs = INF;
    auto up = [&](int l) {
        int d = 1;
        F(i,n) if (w[i]) {
            d++;
            l *= w[i];
        }
        if (best > d || (best == d && leafs > l)) {
            best = d;
            leafs = l;
        }
    };
    F(u,n) {
        w.assign(n,0);
        dfs(u, -1, 0);
        up(1);
        for (int v : g[u]) {
            w.assign(n,0);
            dfs(u, v, 0);
            dfs(v, u, 0);
            up(2);
        }
    }
    cout<<best<<" "<<leafs<<"\n";
}