#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<climits>
#include<string>
#include<set>
#include<numeric>
#include<map>
#include<iostream>
using namespace std;
#define rep(i,n) for(int i = 0;i<((int)(n));i++)
#define reg(i,a,b) for(int i = ((int)(a));i<=((int)(b));i++)
#define irep(i,n) for(int i = ((int)(n)-1);i>=0;i--)
#define ireg(i,a,b) for(int i = ((int)(b));i>=((int)(a));i--)
typedef long long ll;
typedef pair<ll, ll> mp;
ll mod = 1e9+7;

/*
AC
最長パスに注目する．最長パスの長さをLとすると，少なくとも(L+1)/2種類の同型でない頂点がある．
この最適値を達成するには，中央から見た時のグラフの形が対称になるように点を追加すれば良いが，葉の数まで最適化しようとすると，中央が１つの時の自由度が高くなる．
中央が２つ：左右対称にするしかない．
中央が１つ：点対象にする．もしくは，中心の近傍点１つを中央に加える（中央が２つの時に帰着）


コードが汚すぎるのでいつかリファクタリングしたい
*/

int main(void){
	ll n,d[110],d2[110],s,visit[110]={},ans[2]={0,1};
	int max_id=0,max_id2=0;
	vector<int> v[110],c;
	queue<int> Q;
	cin>>n;
	rep(i,n-1){
		ll a,b;
		cin>>a>>b;
		v[a-1].push_back(b-1);
		v[b-1].push_back(a-1);
	}
	//木の頂点に２点間の距離を書き込む
	rep(i,110)d[i]=1e9;
	d[0]=0;
	Q.push(0);
	while(!Q.empty()){
		int p = Q.front();Q.pop();
		rep(i,v[p].size()){
			int q = v[p][i];
			if(d[q]>d[p]+1){
				d[q]=d[p]+1;
				Q.push(q);
			}
		}
	}
	rep(i,n)if(d[max_id]<d[i])max_id=i;
	rep(i,110)d2[i]=1e9;
	Q.push(max_id);
	d2[max_id]=0;
	while(!Q.empty()){
		int p = Q.front();Q.pop();
		rep(i,v[p].size()){
			int q = v[p][i];
			if(d2[q]>d2[p]+1){
				d2[q]=d2[p]+1;
				Q.push(q);
			}
		}
	}
	rep(i,n)if(d2[max_id2]<d2[i])max_id2=i;
	rep(i,110)d[i]=1e9;
	Q.push(max_id2);
	d[max_id2]=0;
	while(!Q.empty()){
		int p = Q.front();Q.pop();
		rep(i,v[p].size()){
			int q = v[p][i];
			if(d[q]>d[p]+1){
				d[q]=d[p]+1;
				Q.push(q);
			}
		}
	}
	//下界を達成できる
	ans[0]=d2[max_id2]/2+1;
	//中央を求める．
	//max_idとmax_id2の真ん中が中央．
	//最初は(d[s],d2[s])=(最大,最小)
	s=max_id;
	while(true){
		bool ok=false;
		if(d[s]==d[max_id]/2 || d2[s]==d2[max_id2]/2)c.push_back(s);//木の中心
		rep(i,v[s].size()){
			ll p=v[s][i];
			if(d[s]>d[p] && d2[s]<d2[p]){
				s=p;
				ok=true;
				break;
			}
		}
		if(!ok)break;
	}
	rep(i,c.size()){
		// cout<<"中央："<<c[i]<<endl;
		visit[c[i]]=1;
	}
	queue<mp> Q2;
	rep(i,c.size())Q2.push({c[i],0});
	int deg_max[110]={};
	while(!Q2.empty()){
		mp p=Q2.front();Q2.pop();
		deg_max[p.second]=max(deg_max[p.second],(int)v[p.first].size());
		rep(i,v[p.first].size()){
			ll q=v[p.first][i];
			if(visit[q]==0){
				Q2.push({q,p.second+1});
				visit[q]=1;
			}
		}
	}
	// rep(i,ans[0])cout<<"deg_max:"<<deg_max[i]<<endl;
	if(c.size()==2){
		rep(i,ans[0]-1)ans[1]*=deg_max[i]-1;
		ans[1]*=2;
	}else{
		// rep(i,ans[0])cout<<"最初のdeg_max:"<<deg_max[i]<<endl;
		deg_max[0]++;
		rep(i,ans[0]-1)ans[1]*=deg_max[i]-1;
		//近傍を新たな中央にする
		rep(i,v[c[0]].size()){
			rep(j,110)deg_max[j]=0;
			rep(j,110)visit[j]=0;
			visit[c[0]]=1;
			visit[v[c[0]][i]]=1;
			Q2.push({c[0],0});
			Q2.push({v[c[0]][i],0});
			while(!Q2.empty()){
				mp p=Q2.front();Q2.pop();
				deg_max[p.second]=max(deg_max[p.second],(int)v[p.first].size());
				rep(i,v[p.first].size()){
					ll q=v[p.first][i];
					if(visit[q]==0){
						Q2.push({q,p.second+1});
						visit[q]=1;
					}
				}
			}
			// rep(j,ans[0])cout<<i<<"番目のdeg_max:"<<deg_max[j]<<endl;
			ll tmp=1;
			rep(j,ans[0]-1)tmp*=deg_max[j]-1;
			tmp*=2;
			ans[1]=min(ans[1],tmp);
		}
	}
	cout<<ans[0]<<" "<<ans[1]<<endl;
	return 0;
}

Measured memory_bytes: 256