#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

typedef tree<
ll,
null_type,
less<ll>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
// ordered_set X;
// *X.find_by_order(i) = ith largest element (counting from zero)
// X.order_of_key(k) = number of items in X < k (strict lt)
template<int MOD> struct modnum {
    int v;
    modnum() : v(0) {}
    modnum(ll _v) : v(_v % MOD) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    friend istream& operator >> (istream& i, modnum& n) { ll v; i >> v; n = modnum(v); return i; }
    friend ostream& operator << (ostream& o, const modnum& n) { return o << n.v; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

    modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
    modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
    modnum& operator *= (const modnum& o) { v = int(ll(v) * ll(o.v) % MOD); return *this; }
    modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }

    modnum pow(ll e) const {
        if (e == 0) return 1;
        if (e & 1) return *this * this->pow(e-1);
        return (*this * *this).pow(e/2);
    }

    modnum inv() const {
        int g = MOD, x = 0, y = 1;
        for (int r = v; r != 0; ) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }

        assert(g == 1);
        assert(y == MOD || y == -MOD);
        return x < 0 ? x + MOD : x;
    }
    modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }

    static int totient() {
        int tot = MOD, tmp = MOD;
        for (int p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
            tot = tot / p * (p - 1);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot = tot / tmp * (tmp - 1);
        return tot;
    }

    static int primitive_root() {
        if (MOD == 1) return 0;
        if (MOD == 2) return 1;

        int tot = totient(), tmp = tot;
        vi tot_pr;
        for (int p = 2; p * p <= tmp; p++) if (tot % p == 0) {
            tot_pr.push_back(p);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot_pr.push_back(tmp);

        for (int r = 2; r < MOD; r++) if (__gcd(r, MOD) == 1) {
            bool root = true;
            for (int p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
            if (root) return r;
        }
        assert(false);
    }

    static modnum generator() { static modnum g = primitive_root(); return g; }
    static int discrete_log(modnum v) {
        static const int M = ceil(sqrt(MOD));
        static unordered_map<int, int> table;
        if (table.empty()) {
            modnum e = 1;
            for (int i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
        }
        static modnum f = generator().pow(totient() - M);

        for (int i = 0; i < M; i++) {
            if (table.count(v.v)) return table[v.v] + i * M;
            v *= f;
        }
        assert(false);
    }

    static modnum fact(int n) {
        static vector<modnum<MOD>> fact = { 1 };
        for (assert(n >= 0); fact.size() <= n; )
            fact.push_back(fact.back() * fact.size());
        return fact[n];
    }

    static modnum finv(int n) {
        static vector<modnum<MOD>> finv = { 1 };
        for (assert(n >= 0); finv.size() <= n; )
            finv.push_back(finv.back() / finv.size());
        return finv[n];
    }

    static modnum ncr(int n, int r) {
        if (r < 0 || n < r) return 0;
        return fact(n) * finv(r) * finv(n - r);
    }
};

constexpr ll MOD = 998244353;
constexpr int IMAX = 450;

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    vb usedrow(IMAX, false);
    vector<vb> used(IMAX, usedrow);

    vector<tuple<int, int, int>> good;
    for (int i=0;i<IMAX;i++) {
        good.push_back(tuple<int, int, int>{0, i , i});
        // cout << 0 << " " << i << " " << i << endl;
    }

    for (int i=1;i<IMAX;i++) {
        // cout << "i = " << i << endl;
        int j = i+1;
        while (j < IMAX) {
            while (j < IMAX && used[i][j]) {
                j++;
            }
            if (j < IMAX) {
                int k = j+1;
                while (k < IMAX && (used[i][k] || used[j][k])) {
                    k++;
                }
                if (k < IMAX) {
                    good.push_back(tuple<int, int, int>{i, j, k});
                    // cout << i << " " << j << " " << k << endl;
                    used[i][j] = true;
                    used[i][k] = true;
                    used[j][k] = true;
                }
            }
            j++;
        }
    }

    // cout << good.size() << endl;

    int N;
    cin >> N;
    vvi adj1(N);
    vvi adj2(N);
    vvi adj3(N);

    int M1;
    cin >> M1;
    for (int i=0;i<M1;i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        adj1[u].push_back(v);
        adj1[v].push_back(u);
    }

    int M2;
    cin >> M2;
    for (int i=0;i<M2;i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        adj2[u].push_back(v);
        adj2[v].push_back(u);
    }

    int M3;
    cin >> M3;
    for (int i=0;i<M3;i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        adj3[u].push_back(v);
        adj3[v].push_back(u);
    }

    vi label1(N, 0);
    vi label2(N, 0);
    vi label3(N, 0);

    vb levels(IMAX, false);
    int max_label = 0;
    for (int i=N-1;i>=0;i--) {
        for (int nbr : adj1[i]) {
            if (nbr > i) levels[label1[nbr]] = true;
            
        }
        while(levels[label1[i]]) label1[i]++;
        max_label = max(max_label, label1[i]);
        for (int j=0;j<=max_label;j++) levels[j] = false;

        for (int nbr : adj2[i]) {
            if (nbr > i) levels[label2[nbr]] = true;
            
        }
        while(levels[label2[i]]) label2[i]++;
        max_label = max(max_label, label2[i]);
        for (int j=0;j<=max_label;j++) levels[j] = false;

        for (int nbr : adj3[i]) {
            if (nbr > i) levels[label3[nbr]] = true;
            
        }
        while(levels[label3[i]]) label3[i]++;
        max_label = max(max_label, label3[i]);
        for (int j=0;j<=max_label;j++) levels[j] = false;
    }

    // for (int i=0;i<N;i++) {
    //     cout << i << " " << label1[i] << " " << label2[i] << " " << label3[i] << endl;
    // }

    vector<modnum<MOD>> wts1(IMAX+1, 0);
    vector<modnum<MOD>> wts2(IMAX+1, 0);
    vector<modnum<MOD>> wts3(IMAX+1, 0);

    modnum<MOD> base = modnum<MOD>(10).pow(18);
    for (int i=0;i<N;i++) {
        wts1[label1[i]] += base.pow(i+1);
        wts2[label2[i]] += base.pow(i+1);
        wts3[label3[i]] += base.pow(i+1);
    }

    // cout << "weights: " << endl;
    // for (int i=0;i<5;i++) {
    //     cout << i << " " << wts1[i] << " " << wts2[i] << " " << wts3[i] << endl;
    // }

    modnum<MOD> ans = 0;

    for (auto gtrip : good) {
        int x = get<0>(gtrip);
        int y = get<1>(gtrip);
        int z = get<2>(gtrip);

        if (x == y  && x == z) {
            ans += wts1[x] * wts2[y] * wts3[z];
        } else if (y == z) {
            ans += wts1[x] * wts2[y] * wts3[y];
            ans += wts1[y] * wts2[x] * wts3[y];
            ans += wts1[y] * wts2[y] * wts3[x];
        } else {
            ans += wts1[x] * wts2[y] * wts3[z];
            ans += wts1[x] * wts2[z] * wts3[y];
            ans += wts1[y] * wts2[x] * wts3[z];
            ans += wts1[y] * wts2[z] * wts3[x];
            ans += wts1[z] * wts2[x] * wts3[y];
            ans += wts1[z] * wts2[y] * wts3[x];
        }
    }

    cout << ans << endl;
    

    return 0;
}

Measured memory_bytes: 17272