#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
typedef long double ld;
const ld INF = (ld)10000000000000;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef complex<ld> Point;
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;

int n;
vector<int> G[100];

bool used[100];
int mostfar(int id) {
	int ret = 0;
	fill(used, used + n, false); used[id] = true;
	queue<int> q; q.push(id);
	while (!q.empty()) {
		int x = q.front(); q.pop();
		ret = x;
		rep(j, G[x].size()) {
			int to = G[x][j];
			if (used[to])continue;
			used[to] = true; q.push(to);
		}
	}
	return ret;
}
int d[100][100];

ll calc(vector<vector<int>> &v) {
	ll ret = v.size();
	while (!v.empty()) {
		int ma = 0;
		rep(i, v.size()) {
			rep(j, v[i].size()) {
				ma = max(ma, (int)G[v[i][j]].size() - 1);
			}
		}
		//cout << "hello "<<ma << endl;
		vector<vector<int>> u;
		rep(i, v.size()) {
			vector<int> z;
			rep(j, v[i].size()) {
				int cur = v[i][j];
				rep(k, G[cur].size()) {
					int to = G[cur][k];
					if (used[to])continue;
					used[to] = true;
					z.push_back(to);
				}
			}
			if(!z.empty())u.push_back(z);
		}
		ma = max(ma, 1);
		ret *= ma;
		v = u;
	}
	return ret;
}
int main() {
	cin >> n;
	rep(i, n) {
		rep(j, n) {
			if (i == j)d[i][j] = 0;
			else d[i][j] = mod;
		}
	}
	rep(i, n - 1) {
		int a, b; cin >> a >> b; a--; b--;
		d[a][b] = d[b][a] = 1;
		G[a].push_back(b); G[b].push_back(a);
	}
	int l = mostfar(0); int r = mostfar(l);
	rep(k, n) {
		rep(i, n) {
			rep(j, n) {
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
	fill(used, used + n, false);
	int len = d[l][r];
	vector<vector<int>> v;
	if (len % 2 == 0) {
		int chk = 0;
		rep(i, n) {

			if (d[i][l] == len / 2 && d[i][r] == len / 2) {
				used[i] = true; chk = i;
				rep(j, G[i].size()) {
					int to = G[i][j];
					v.push_back({ to });
					used[to] = true;
				}
			}
		}
		//cout << v.size() << endl;
		ll ans = calc(v);
		//cout << ans << endl;
		rep(i, G[chk].size()) {
			v.clear();
			int j = G[chk][i];
			fill(used, used + n, false);
			used[chk] = used[j] = true;
			v.push_back({ chk });
			v.push_back({ j });
			//ll z = calc(v);
			//cout << z << endl;
			ans = min(ans, calc(v));
		}
		cout << len / 2+1 << " " << ans << endl;
	}
	else {
		rep(i, n) {
			if (d[i][l] == len / 2 && d[i][r] == len / 2 + 1) {
				used[i] = true; v.push_back({ i });
			}
			if (d[i][l] == len / 2 + 1 && d[i][r] == len / 2) {
				used[i] = true; v.push_back({ i });
			}
		}
		//cout << v.size() << endl;
		ll ans = calc(v);
		cout << (len + 1) / 2 << " " << ans << endl;
	}
	//stop
	return 0;
}

Measured memory_bytes: 256