//#define NDEBUG
#define _CRT_SECURE_NO_WARNINGS
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>

template <class Integral = std::size_t> class irange {
	const Integral f, l;

public:
	using value_type = Integral;
	using reference = value_type;
	class irangeitr {
		friend irange;
		value_type i;
		irangeitr(value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		reference operator*() const noexcept { return i; }
		bool operator!=(const irangeitr &x) const noexcept { return i != x.i; }
	};
	irange(value_type first, value_type last) noexcept : f(first), l(last) {}
	irangeitr begin() const noexcept { return irangeitr(f); }
	irangeitr end() const noexcept { return irangeitr(l); }
};
template <class Integral = std::size_t> class Rirange {
	const Integral f, l;

public:
	using value_type = Integral;
	using reference = value_type;
	class Rirangeitr {
		friend Rirange;
		value_type i;
		Rirangeitr(value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		reference operator*() const noexcept { return i - 1; }
		bool operator!=(const Rirangeitr &x) const noexcept { return i != x.i; }
	};
	Rirange(value_type first, value_type last) noexcept : f(first), l(last) {}
	Rirangeitr begin() const noexcept { return Rirangeitr(l); }
	Rirangeitr end() const noexcept { return Rirangeitr(f); }
};
template <class T> bool maxi(T &a, const T &b) {
	if (b < a)
		return 0;
	a = b;
	return 1;
}
template <class T> bool mini(T &a, const T &b) {
	if (a < b)
		return 0;
	a = b;
	return 1;
}
template <class T> bool smaxi(T &a, const T &b) {
	if (a < b) {
		a = b;
		return 1;
	}
	return 0;
}
template <class T> bool smini(T &a, const T &b) {
	if (b < a) {
		a = b;
		return 1;
	}
	return 0;
}
struct customIO {
	int c;
	bool f;
	std::array<int, 30> buf;
	void get_c() { c = fgetc(stdin); }
	void put_c(int x) { fputc(x, stdout); }
	bool vacant() { return c == ' ' || c == '\n'; }
	operator int() { return 0; }

	// in

	void cueing() {
		while (get_c(), vacant())
			;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
		d = 0;
		f = 0;
		cueing();
		if (c == '-')
			f = 1, get_c();
		do
			d = d * 10 + c - '0';
		while (get_c(), !vacant());
		if (f)
			d = -d;
		return *this;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
		d = 0;
		cueing();
		do
			d = d * 10 + c - '0';
		while (get_c(), !vacant());
		return *this;
	}
	customIO &operator>>(char &d) {
		cueing();
		d = c;
		return *this;
	}
	customIO &operator>>(double &d) {
		scanf("%lf", &d);
		return *this;
	}
	customIO &operator>>(std::string &d) {
		d.clear();
		cueing();
		do
			d.push_back(c);
		while (get_c(), !vacant());
		return *this;
	}
	template <class T> T input() {
		T d;
		*this >> d;
		return d;
	}

	// out

	template <class T>
	auto operator<<(T d) ->
		typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
		c = 0;
		f = 0;
		if (d < static_cast<T>(0))
			f = 1, d = -d;
		while (d)
			buf[c++] = d % 10 + '0', d /= 10;
		if (!c)
			buf[c++] = '0';
		if (f)
			put_c('-');
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	template <class T>
	auto operator<<(T d) ->
		typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
		c = 0;
		while (d)
			buf[c++] = d % 10 + '0', d /= 10;
		if (!c)
			buf[c++] = '0';
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	customIO &operator<<(char d) {
		put_c(d);
		return *this;
	}
	customIO &operator<<(const std::string &d) {
		for (const auto e : d)
			put_c(e);
		return *this;
	}
	customIO &operator<<(const char *d) {
		while (*d != '\0')
			put_c(*(d++));
		return *this;
	}
	customIO &operator<<(double d) {
		/*
		printf("%1.9f",d);
		/*/
		printf("%f", d);
		//*/
		return *this;
	}
	void endl() { put_c('\n'); }
	void space() { put_c(' '); }
} IO;

using int32 = std::int_fast32_t;
using int64 = std::int_fast64_t;
using uint32 = std::uint_fast32_t;
using uint64 = std::uint_fast64_t;
using intl32 = std::int_least32_t;
using intl64 = std::int_least64_t;
using uintl32 = std::uint_least32_t;
using uintl64 = std::uint_least64_t;

#include <algorithm>
#include <utility>
#include <vector>
#include<functional>


using Graph = std::vector<std::vector<uint32>>;

int main() {
	const auto n = IO.input<uint32>();
	Graph G(n);
	for (const auto i : irange<>(1, n)) {
		uint32 a, b;
		IO >> a >> b;
		--a;
		--b;
		G[a].emplace_back(b);
		G[b].emplace_back(a);
	}
	std::vector<uint32> dist(n, 10000);
	std::function<void(uint32, uint32)> cho = [&](uint32 v, uint32 now) {
		++now;
		for (const auto e : G[v])
			if (smini(dist[e], now))
				cho(e, now);
	};
	dist[0] = 0;
	cho(0, 0);
	const uint32 left = std::max_element(dist.begin(), dist.end())-dist.begin();
	std::fill(dist.begin(), dist.end(), 10000);
	dist[left] = 0;
	cho(left, 0);
	const uint32 right = std::max_element(dist.begin(), dist.end()) - dist.begin();
	const uint32 ans = (dist[right] / 2) + 1;
	uint32 mid1 = 10000, mid2=10000;
	{
		std::vector<char> exi(n, 0);
		exi[right] = 1;
		std::function<void(uint32, uint32)> cho1 = [&](uint32 v, uint32 prev) {
			for (const auto e : G[v])
				if (e != prev)
					cho1(e, v), exi[v] |= exi[e];
		};
		cho1(left, n);
		for (const auto i : irange<>(0, n))
			if (exi[i] && (dist[i] == dist[right] / 2 || dist[i] == (dist[right] + 1) / 2))
				if (mid1 == 10000)
					mid1 = i;
				else
					mid2 = i;
	}
	uint64 ansmin = UINT64_MAX;
	if (mid2 == 10000) {
		std::vector<uint64> maxdeg(n, 0);
		std::function<void(uint32, uint32,uint32)> dfs = [&](uint32 v, uint32 prev,uint32 d) {
			uint64 cnt = 0;
			for (const auto e : G[v])
				if (e != prev)
					++cnt, dfs(e, v, d + 1);
			smaxi(maxdeg[d], cnt);
		};
		dfs(mid1, n, 0);
		uint32 itr = 0;
		uint64 cur = 1;
		while (maxdeg[itr] != 0)
			cur *= maxdeg[itr], ++itr;
		smini(ansmin, cur);
		for (const auto e : G[mid1]) {
			std::fill(maxdeg.begin(), maxdeg.end(), 0);
			dfs(mid1, e, 0);
			dfs(e, mid1, 0);
			itr = 0;
			cur = 2;
			while (maxdeg[itr] != 0)
				cur *= maxdeg[itr], ++itr;
			smini(ansmin, cur);
		}
	}
	else {
		std::vector<uint64> maxdeg(n, 0);
		std::function<void(uint32, uint32, uint32)> dfs = [&](uint32 v, uint32 prev, uint32 d) {
			uint64 cnt = 0;
			for (const auto e : G[v])
				if (e != prev)
					++cnt, dfs(e, v, d + 1);
			smaxi(maxdeg[d], cnt);
		};
		dfs(mid1, mid2, 0);
		dfs(mid2, mid1, 0);
		uint32 itr = 0;
		uint64 cur = 2;
		while (maxdeg[itr] != 0)
			cur *= maxdeg[itr], ++itr;
		smini(ansmin, cur);
	}
	IO << ans << " " << ansmin << "\n";
	return 0;
}

Measured memory_bytes: 256