#include<bits[表情]dc++.h>
#include<unordered_map>
using namespace std;
//#define int long long
#define RG register
#define bit(x) (1LL << (x))
#define lowbit(x) (x & -x)
#define sq(x) ((x) * (x))
#define rep(a, b, c, d) for (int a = (b); a <= (c); a += (d))
#define fep(a, b, c, d) for (int a = (b); a >= (c); a -= (d))
#define PLL pair<long, long>
using unll = unsigned long long;
using ll = long long;
/*--fast read--*/
// use : n = read<int>();
template<typename T> T read() {
T X = 0; bool flag = true; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') flag = false; ch = getchar(); }
while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar(); }
if (flag) return X;
return ~(X - 1);
}
// 毒瘤 只能Linux上用 win上报错
//template<typename T> T read() {
// T X = 0; bool flag = true; char ch = getchar_unlocked(); // 比getchar还快
// while (ch < '0' || ch > '9') { if (ch == '-') flag = false; ch = getchar_unlocked(); }
// while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar_unlocked(); }
// if (flag) return X;
// return ~(X - 1);
//}
// use : write<ll>(n);
template<typename T> void write(T X) {
if (X < 0) { putchar('-'); X = ~(X - 1); }
int s[100], top = 0;
while (X) { s[++top] = X % 10; X /= 10; }
if (!top) s[++top] = 0;
while (top) putchar(s[top--] + '0');
}
/*--const--*/
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3f;
const long long MODE = 998244353;
const int dx[] = { 1, 0,-1, 0, 1, 1,-1,-1 };
const int dy[] = { 0,-1, 0, 1, -1, 1,-1, 1 };
const double eps = 1e-8;
double Pi = acos(-1.0);
/*--math--*/
long long qpow(long long x, long long y) {
x %= MODE;
long long res = 1;
while (y) {
if (y & 1) res = res * x % MODE;
x = x * x % MODE;
y >>= 1;
}
return res;
}
long long gcd(long long a, long long b) { // 最大公约数
while (b ^= a ^= b ^= a %= b)
;
return a;
}
long long lcm(long long a, long long b) { // 最小公倍数
return a / gcd(a, b) * b;
}
/*------------CODE------------*/
// int months[15] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//priority_queue<ll> pq;//这是一个大根堆q
//priority_queue<int, vector<int>, greater<int> >q;//这是一个小根堆q
//priority_queue<ll, vector<ll>, greater<ll> >pq; // 小根
const long long N = 1e6 + 50;
const long long M = 2e6 + 50;
ll n, m;
/[表情]ector<ll>adj[N];
vector<pair<ll, ll> >vp;
vector<ll>cst[N];
ll fa[N];
ll sz[N];
ll fp[N];
ll findfa(ll k) {
if (k == fa[k]) return k;
else return fa[k] = findfa(fa[k]);
}
ll p[N];
void dfs(ll x, ll fa)
{
for (auto& y : cst[x])
if (y != fa) {
fp[y] = fp[x] + 1;
p[y] = x, dfs(y, x);
}
}
void solve() {
cin >> n;
rep(i, 1, n, 1) {
fa[i] = i;
sz[i] = 1;
}
m = n - 2;
ll u, v;
rep(i, 0, m, 1) {
cin >> u >> v;
vp.push_back({ u, v });
}
rep(i, 0, m, 1) {
cin >> u >> v;
cst[u].push_back(v);
cst[v].push_back(u);
}
dfs(1, 0);
//for(int i = 1;i <= n;++i) cout<<p[i]<<' '; cout<<'\n';
ll ans = 1;
rep(i, 0, m, 1) {
u = vp[i].first;
v = vp[i].second;
ll fu = findfa(u);
ll fv = findfa(v);
if (fu == fv) continue;
//if (!(findfa(p[fu]) == findfa(fv) || findfa(p[fv]) == findfa(fu)))
//{
// //cout << '0' << '\n';
// cout << "0\n";
// return;
//}
if (fp[fu] > fp[fv]) swap(fu, fv);
if (!(/*findfa(p[fu]) == findfa(fv) ||*/ findfa(p[fv]) == findfa(fu)))
{
//cout << '0' << '\n';
//cout << " first ";
cout << "0\n";
return;
}
fa[fv] = fu;
ans = (((ans * sz[fu]) % MODE) * sz[fv]) % MODE;
sz[fu] = (sz[fu] + sz[fv]);
//ans *= sz[fv] % MODE;
//cout << " ans " << ans << '\n';
//cout << " sz " << sz[fu] << '\n';
//ans %= MODE;
}
// rep(i, 1, n, 1) {
// cout << sz[i] << ' ';
// }cout << '\n';
ll cnt = 1;
ll num = findfa(fa[1]);
//cout << " fa ";
rep(i, 2, n, 1) {
if (num == findfa(fa[i]))cnt++;
//cout << fa[i] << ' ';
// if (fa[i] == i) cnt++;
}//cout << '\n';
//cout << ans << '\n';
//cout << n << '\n';
//cout << cnt << '\n';
if (cnt == n) {
//cout << "***** ";
cout << qpow(ans, MODE - 2) % MODE << '\n';
}
else {
//cout << " final ";
cout << "0\n";
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//freopen("wrt.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T = 1;
//cin >> T;
while (T--) {
solve();
}
}