#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);
	}
	//木の頂点に２点間の距離を書き込む
	//max_idを求めるための前処理
	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;
	//頂点max_idからの距離
	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;
	//頂点max_id2からの距離
	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())visit[c[i]]=1;//cが中央のindex
	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;
			}
		}
	}
	if(c.size()==2){
		rep(i,ans[0]-1)ans[1]*=deg_max[i]-1;
		ans[1]*=2;
	}else{
		deg_max[0]++;//最初は親要素がないので-1する分を相殺
		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;
					}
				}
			}
			//葉の最小値を更新する
			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