#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cctype>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstdio>
#include <functional>
using namespace std; 
// #define DEBUG(x) cout << '>' << #x << ':' << x << endl;
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
const int nINF = 1<<31;
typedef long long ll;
const ll INF = 0x7fffffffffffffffLL;
typedef unsigned long long ull;
typedef pair<ll, ll> pii;
typedef pair<char, int> pci;

/////////////////////////////////////////////////////////////////////
const ll N = 301;
ll n, d[N], l[N], diam, ans1, ans2 = INF;
vector<ll> g[N];
set<pii> poss;

ll tryroot(ll s) {
	fill(d, d+n+1, 0);
	fill(l, l+n+1, 0);
	queue<ll> next;
	d[s] = 0;
	l[0] = g[s].size();
	next.push(s);
	while(!next.empty()) {
		ll cur = next.front();
		next.pop();
		ll lev = d[cur];
		l[lev] = max(l[lev], (ll)(g[cur].size()-1));
		for(ll v : g[cur]) {
			if(!d[v] && v != s) {
				d[v] = 1+d[cur];
				next.push(v);
			}
		}
	}
	int i = 0;
	ll res = 1;
	while(l[i]) {
		// DEBUG(i);
		// DEBUG(l[i]);
		res *= l[i++];
	}
	return res;
}

ll tryroot(pii s) {
	fill(d, d+n+1, 0);
	fill(l, l+n+1, 0);
	queue<ll> next;
	d[s.first] = 0;
	d[s.second] = 0;
	next.push(s.first);
	next.push(s.second);
	while(!next.empty()) {
		ll cur = next.front();
		next.pop();
		ll lev = d[cur];
		// DEBUG(cur);
		// DEBUG(g[cur].size()-1);
		l[lev] = max(l[lev], (ll)(g[cur].size()-1));
		for(ll v : g[cur]) {
			if(!d[v] && v != s.first && v != s.second) {
				d[v] = 1+d[cur];
				next.push(v);
			}
		}
	}
	int i = 0;
	ll res = 1;
	while(l[i]) {
		// DEBUG(i);
		// DEBUG(l[i]);
		res *= l[i++];
	}
	return 2*res;
}

void safeinsert(pii x) {
	if(poss.count(x) == 0 && poss.count({x.second, x.first}) == 0) poss.insert(x);
}

pii far(ll s) {
	fill(d, d+n+1, 0);
	queue<ll> next;
	next.push(s);
	d[s] = 1;
	pii res = {1, s};
	while(!next.empty()) {
		ll cur = next.front();
		next.pop();
		for(ll v : g[cur]) {
			if(!d[v]) {
				next.push(v);
				d[v] = 1+d[cur];
				res = max(res, {d[v], v});
			}
		}
	}
	return res;
}

ll diameter() {
	return far(far(1).second).first;
}

//start dis at 0
bool getposs(ll s, ll p, ll dis) {
	// DEBUG(s);
	// DEBUG(dis);
	if(g[s].size() == 1 && p != -1) return dis+1 == diam;
	bool ever = false;
	for(ll v : g[s]) {
		bool cur = false;
		if(v != p) cur = getposs(v, s, dis+1);
		ever |= cur;
		if(cur && (dis == diam/2 || dis == (diam-1)/2)) {
			if(diam & 1) {
				safeinsert({s, 0});
			} else {
				if(dis == diam/2) safeinsert({s, p});
			}
		}
	}
	// DEBUG(s);
	// DEBUG(ever);
	return ever;
}

int main() {
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(7);
    cin >> n;
    REP(i, n-1) {
    	ll a, b;
    	cin >> a >> b;
    	g[a].push_back(b);
    	g[b].push_back(a);
    }
    if(n == 2) {
    	cout << "1 2" << endl;
    	exit(0);
    }
    diam = diameter();
    // DEBUG(diam);
    ans1 = (diam+1)/2;
    FOR(i, 1, n) {
    	if(g[i].size() == 1) {
    		getposs(i, -1, 0);
    	}
    }
    if(diam & 1) {
    	int root = poss.begin()->first;
    	for(int v : g[root]) {
    		safeinsert({root, v});
    	}
    }
    for(pii p : poss) {
    	// DEBUG(p.first);
    	// DEBUG(p.second);
    	if(p.second) ans2 = min(ans2, tryroot(p));
    	else ans2 = min(ans2, tryroot(p.first));
    }
    cout << ans1 << ' ' << ans2 << endl;

    return 0;
}

Measured memory_bytes: 256