#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
using namespace std;
template <typename Tp>
inline void read(Tp &x) {
  static char c;
  static bool neg;
  x = 0, c = getchar(), neg = false;
  for (; !isdigit(c); c = getchar()) {
    if (c == '-') {
      neg = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (neg) {
    x = -x;
  }
}
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;
const int N = 4000 + 5;
const int K = 75 + 5;
inline int power(int base, int exp) {
  int res = 1;
  while (exp > 0) {
    if (exp & 1) {
      res = (long long)res * base % MOD;
    }
    base = (long long)base * base % MOD;
    exp >>= 1;
  }
  return res;
}
inline int inv(int x) { return power(x, MOD - 2); }
inline int inc(int &x, const int &y) {
  x += y;
  if (x >= MOD) {
    x -= MOD;
  } else if (x < 0) {
    x += MOD;
  }
  return x;
}
int fac[N], facInv[N];
inline void init() {
  fac[0] = facInv[0] = 1;
  for (int i = 1; i < N; ++i) {
    fac[i] = (long long)fac[i - 1] * i % MOD;
  }
  facInv[N - 1] = inv(fac[N - 1]);
  for (int i = N - 2; i >= 1; --i) {
    facInv[i] = (long long)facInv[i + 1] * (i + 1) % MOD;
  }
}
inline int C(int n, int m) {
  if (n < m) {
    return 0;
  } else {
    return (long long)fac[n] * facInv[m] % MOD * facInv[n - m] % MOD;
  }
}
namespace G {
int head[N], E = 0;
bool vis[N];
struct Edge {
  int to, next;
} e[N * 2];
inline void addEdge(int u, int v) {
  e[++E] = (Edge){v, head[u]};
  head[u] = E;
}
inline void addE(int u, int v) {
  addEdge(u, v);
  addEdge(v, u);
}
inline void clear() {
  E = 0;
  memset(head, 0, sizeof(head));
}
}  // namespace G
namespace GetRoot {
using G::e;
using G::head;
using G::vis;
int root, rootMax, nowSize;
int siz[N];
void getRoot(int u, int fa) {
  siz[u] = 1;
  int max = 0;
  for (int i = head[u], v; v = e[i].to, i; i = e[i].next) {
    if (v != fa && !vis[v]) {
      getRoot(v, u);
      siz[u] += siz[v];
      max = std::max(max, siz[v]);
    }
  }
  max = std::max(max, nowSize - max);
  if (max < rootMax) {
    rootMax = max;
    root = u;
  }
}
}  // namespace GetRoot
inline int findRoot(int u, int size) {
  using GetRoot::getRoot;
  using GetRoot::nowSize;
  using GetRoot::root;
  using GetRoot::rootMax;
  nowSize = size;
  rootMax = INF;
  getRoot(u, 0);
  return root;
}
int n1, n2, k;
int L[N], R[N];
int f[N][K], g[N][K];
namespace Work {
using G::e;
using G::head;
using G::vis;
int ans[N];
unordered_map<int, int> id;
vector<int> vec;
void explore(int u, int fa) {
  id[u] = (int)vec.size();
  vec.emplace_back(u);
  for (int i = head[u], v; v = e[i].to, i; i = e[i].next) {
    if (v != fa && !vis[v]) {
      explore(v, u);
    }
  }
}
inline void dp(int u) {
  for (int i = 0; i < (int)vec.size(); ++i) {
    fill(f[i], f[i] + k + 1, 0);
    fill(g[i], g[i] + k + 1, 0);
  }
  f[id[u]][0] = 1;
  g[id[u]][0] = 1;
  for (int dk = 1; dk <= k; ++dk) {
    for (int du = 0, dv; du < (int)vec.size(); ++du) {
      for (int i = head[vec[du]], v; v = e[i].to, i; i = e[i].next) {
        if (!vis[v]) {
          dv = id[v];
          if (v != u || dk == 1) {
            inc(f[du][dk], f[dv][dk - 1]);
          }
          inc(g[du][dk], g[dv][dk - 1]);
        }
      }
    }
  }
  for (int i = 0; i <= k; ++i) {
    inc(ans[i], g[id[u]][i]);
  }
  for (int dk = 0; dk <= k; ++dk) {
    for (int a = 0, b = dk; a <= dk; ++a, --b) {
      for (int i = 0; i < (int)vec.size(); ++i) {
        if (vec[i] != u) {
          inc(ans[dk], (long long)f[i][a] * g[i][b] % MOD);
        }
      }
    }
  }
}
void dfs(int u) {
  id.clear();
  vec.clear();
  explore(u, 0);
  u = findRoot(u, (int)vec.size());
  dp(u);
  vis[u] = true;
  for (int i = head[u], v; v = e[i].to, i; i = e[i].next) {
    if (!vis[v]) {
      dfs(v);
    }
  }
}
}  // namespace Work
inline void solve() {
  using G::vis;
  using Work::ans;
  using Work::dfs;
  memset(vis, 0, sizeof(vis));
  memset(ans, 0, sizeof(ans));
  dfs(1);
}
int main() {
  init();
  read(n1), read(n2), read(k);
  for (int i = 1, u, v; i < n1; ++i) {
    read(u), read(v);
    G::addE(u, v);
  }
  solve();
  copy(Work::ans, Work::ans + k + 1, L);
  G::clear();
  for (int i = 1, u, v; i < n2; ++i) {
    read(u), read(v);
    G::addE(u, v);
  }
  solve();
  copy(Work::ans, Work::ans + k + 1, R);
  int ans = 0;
  for (int i = 0; i <= k; ++i) {
    inc(ans, (long long)L[i] * R[k - i] % MOD * C(k, i) % MOD);
  }
  printf("%d\n", ans);
}
