#define _USE_MATH_DEFINES
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <queue>
#include <algorithm>
#include <climits>
#include <cstring>
#include <cmath>
#include <stack>
#include <iomanip>
#include <tuple>
#include <functional>
#include <cfloat>
#include <map>

#define int long long
#define CONTAINS(v,n) (find((v).begin(), (v).end(), (n)) != (v).end())
#define SORT(v) sort((v).begin(), (v).end())
#define RSORT(v) sort((v).rbegin(), (v).rend())
#define ARY_SORT(a, size) sort((a), (a)+(size))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define REMOVE(v,a) (v.erase(remove((v).begin(), (v).end(), (a)), (v).end()))
#define REVERSE(v) (reverse((v).begin(), (v).end()))
#define LOWER_BOUND(v,a) (lower_bound((v).begin(), (v).end(), (a)))
#define UPPER_BOUND(v,a) (upper_bound((v).begin(), (v).end(), (a)))
#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define CONTAINS_MAP(m, a) (m).find((a)) != m.end()
using namespace std;

int N;
vector<int> link[101];
int len[101];

int get_len(int n)
{
	queue<int> q;
	bool flg[100] = {};
	flg[n] = true;
	q.push(n);

	int l = 0;
	while (true)
	{
		int q_cnt = q.size();
		REP(i, q_cnt)
		{
			int n = q.front();
			q.pop();
			for (int a : link[n])
			{
				if (!flg[a])
				{
					flg[a] = true;
					q.push(a);
				}
			}
		}
		if (q.size() == 0) break;
		l++;
	}
	return l;
}

void set_len()
{
	REP(i, N)
	{
		len[i] = get_len(i);
	}
	//queue<int> q;
	//REP(i, N)
	//{
	//	if (link[i].size() == 1)
	//	{
	//		len[i] = 1;
	//		q.push(i);
	//	}
	//}

	//int l = 2;
	//while (q.size() > 0)
	//{
	//	int q_cnt = q.size();
	//	REP(i, q_cnt)
	//	{
	//		int n = q.front();
	//		q.pop();
	//		for (int a : link[n])
	//		{
	//			if (len[a] < l)
	//			{
	//				len[a] = l;
	//				q.push(a);
	//			}
	//		}
	//	}
	//	l++;
	//}
}

void get_out(int s, int ignore, int out[100])
{
	if (s < 0) return;

	bool flg[100] = {};
	queue<int> q;
	q.push(s);
	flg[s] = true;

	int loop = 0;
	while (q.size() > 0)
	{
		int q_cnt = q.size();
		REP(i, q_cnt)
		{
			int n = q.front();
			q.pop();
			int l_size = 0;
			for (int l : link[n])
			{
				if (!flg[l] && l != ignore)
				{
					l_size++;
				}
			}
			out[loop] = MAX(out[loop], l_size);
			for (int a : link[n])
			{
				if (!flg[a] && a != ignore)
				{
					flg[a] = true;
					q.push(a);
				}
			}
		}
		loop++;
	}
}

int get_ret(int a, int b)
{
	int a_out[100] = {};
	int b_out[100] = {};
	get_out(a, b, a_out);
	get_out(b, a, b_out);
	int ret = 1;
	for (int i = 0; i < N; i++)
	{
		int a = MAX(a_out[i], 1);
		int b = MAX(b_out[i], 1);
		int c = MAX(a, b);
		ret *= c;
	}
	return ret;
}

signed main()
{
	cin >> N;
	REP(i, N - 1)
	{
		int a, b;
		cin >> a >> b;
		link[a - 1].push_back(b - 1);
		link[b - 1].push_back(a - 1);
	}

	set_len();

	int max_len = INT_MAX;
	vector<int> max_list;
	REP(i, N)
	{
		if (max_len == len[i])
		{
			max_list.push_back(i);
		}
		if (max_len > len[i])
		{
			max_len = len[i];
			max_list.clear();
			max_list.push_back(i);
		}
	}

	if (max_list.size() == 1)
	{
		int top = max_list[0];
		int min_ret = get_ret(top, -1);
		for (int l : link[top])
		{
			int ret = get_ret(top, l);
			min_ret = MIN(min_ret, ret * 2);
		}
		cout << (max_len + 1) << " " << min_ret << endl;
	}
	else
	{
		cout << max_len << " " << (get_ret(max_list[0], max_list[1]) * 2) << endl;
	}
}







Measured memory_bytes: 256