#include <bits/stdc++.h>   using namespace std;   const int mod = 998244353;   const int M = 80;   const int N = 4100;   long long c[M][M], m;   struct Tree {     struct Node {       int ne, to;     } e[2 * N];     int vis[N], tot = 0, he[N], sz[N], mx[N], q[N], n, rp, mn;     long long step[M], f[N][M], g[N][M], tmp[M], ans[M];     void add(int x, int y) {       e[++tot].ne = he[x];       he[x] = tot;       e[tot].to = y;     }     void addedge(int x, int y) {       add(x, y);       add(y, x);     }     void dfs1(int x, int fa) {       int i, y;       sz[x] = 1;       mx[x] = 0;       for (i = he[x]; i; i = e[i].ne) {         y = e[i].to;         if ((!vis[y]) && (y != fa)) {           dfs1(y, x);           sz[x] += sz[y];           if (sz[y] > mx[x]) mx[x] = sz[y];         }       }     }     void dfsrt(int now, int x, int fa, int &rt) {       int i, y;       mx[x] = max(mx[x], sz[now] - sz[x]);       if (mx[x] < mn) {         mn = mx[x];         rt = x;       }       for (i = he[x]; i; i = e[i].ne) {         y = e[i].to;         if ((!vis[y]) && (y != fa)) dfsrt(now, y, x, rt);       }     }     void dfs2(int x, int fa) {       int i, y;       q[++rp] = x;       for (i = he[x]; i; i = e[i].ne) {         y = e[i].to;         if ((!vis[y]) && (y != fa)) dfs2(y, x);       }     }     void divide(int x) {       int rt, i, j, k, y;       mn = n;       dfs1(x, 0);       dfsrt(x, x, 0, rt);       vis[rt] = 1;       for (i = he[rt]; i; i = e[i].ne)         if (!vis[e[i].to]) divide(e[i].to);       vis[rt] = 0;       rp = 0;       dfs2(rt, 0);       memset(step, 0, sizeof(step));       for (i = he[rt]; i; i = e[i].ne) {         y = e[i].to;         if (!vis[y])           for (j = 0; j <= m - 2; j++)             step[j + 2] = (step[j + 2] + f[y][j]) % mod;       }       memset(f[rt], 0, sizeof(f[rt]));       f[rt][0] = 1;       for (i = 1; i <= m; i++)         for (j = 2; j <= i; j++)           f[rt][i] = (f[rt][i] + f[rt][i - j] * step[j]) % mod;       for (i = 2; i <= rp; i++) {         memset(tmp, 0, sizeof(tmp));         for (j = 2; j <= m; j++)           for (k = 0; k <= j - 2; k++)             tmp[j] = (tmp[j] + g[q[i]][k] * f[rt][j - k - 2]) % mod;         for (j = 2; j <= m; j++)           for (k = 0; k <= j - 2; k++)             f[q[i]][j] = (f[q[i]][j] + g[q[i]][k] * tmp[j - k]) % mod;       }       for (i = 1; i <= rp; i++) memset(g[q[i]], 0, sizeof(g[q[i]]));       g[x][0] = 1;       for (i = 1; i <= m; i++)         for (j = 1; j <= rp; j++)           for (k = he[q[j]]; k; k = e[k].ne) {             y = e[k].to;             if (!vis[y]) g[q[j]][i] = (g[q[j]][i] + g[y][i - 1]) % mod;           }     }     void solve() {       divide(1);       for (int i = 0; i <= m; i++)         for (int j = 1; j <= n; j++) ans[i] = (ans[i] + f[j][i]) % mod;     }   } tr1, tr2;   int main() {     int i, j, k, x, y;     long long out;     scanf( %d%d%d , &tr1.n, &tr2.n, &m);     for (i = 1; i < tr1.n; i++) {       scanf( %d%d , &x, &y);       tr1.addedge(x, y);     }     for (i = 1; i < tr2.n; i++) {       scanf( %d%d , &x, &y);       tr2.addedge(x, y);     }     for (i = 0; i <= m; i++) c[i][0] = 1;     for (i = 1; i <= m; i++)       for (j = 1; j <= i; j++) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;     tr1.solve();     tr2.solve();     out = 0;     for (i = 0; i <= m; i++)       out = (out + (c[m][i] * tr1.ans[i]) % mod * tr2.ans[m - i]) % mod;     printf( %I64d n , out);     return 0;   }