#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
const int maxM = 640000 * 2 + 500000 + 10;
const int D = 8;
typedef unsigned long long ull;
int maxd;
struct node {
    int a, b;
};
void Add(int &x, int y) { if ((x += y) >= mod) x -= mod; }
node& operator += (node &a, const node &b) {
    Add(a.a, b.a);
    Add(a.b, b.b);
    return a;
}
node& operator *= (node &a, const node &b) {
    a.b = (1ll * a.a * b.b + 1ll * a.b * b.a) % mod;
    a.a = 1ll * a.a * b.a % mod;
    return a;
}
node operator + (node a, const node &b) {
    return a += b;
}
node operator * (node a, const node &b) {
    return a *= b;
}
map <int, int> out[500010];
vector <int> son[maxM];
node W[maxM];
int U[maxM], V[maxM];
int n, m, q, cnt;
int que[maxM], qcnt, vis[maxM], type[maxM], rt, dep[maxM];
struct matrix {
    node a[4][4];
    matrix() {
        memset(this, 0, sizeof(matrix));
    }
    node* operator [](int x) { return a[x]; }
    const node* operator [](int x) const { return a[x]; }
} a[maxM], t[2100000], I;
ull tttmpa[4][4], tttmpb[4][4];
matrix operator * (const matrix &a, const matrix &b) {
    matrix ans;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) tttmpa[i][j] = tttmpb[i][j] = 0;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) {
            ull tmp = a[i][j].a, tmp2 = a[i][j].b;

            tttmpa[i][0] += tmp * b[j][0].a;
            tttmpb[i][0] += tmp * b[j][0].b;

            tttmpa[i][1] += tmp * b[j][1].a;
            tttmpb[i][1] += tmp * b[j][1].b;

            tttmpa[i][2] += tmp * b[j][2].a;
            tttmpb[i][2] += tmp * b[j][2].b;

            tttmpa[i][3] += tmp * b[j][3].a;
            tttmpb[i][3] += tmp * b[j][3].b;

            tttmpb[i][0] += tmp2 * b[j][0].a;
            tttmpb[i][1] += tmp2 * b[j][1].a;
            tttmpb[i][2] += tmp2 * b[j][2].a;
            tttmpb[i][3] += tmp2 * b[j][3].a;
        }
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) ans[i][j] = {int(tttmpa[i][j] % mod), int(tttmpb[i][j] % mod)};
    return ans;
}
node ans[1000010][4];
int pnt[1000010];
int wson[maxM], fa[maxM], lfa[maxM], sze[maxM];
int keys[maxM][2];
void dfs(int cur) {
    maxd = max(maxd, dep[cur]);
    sze[cur] = 1;
    for (auto i : son[cur]) {
        dep[i] = dep[cur] + 1, dfs(i);
        sze[cur] += sze[i];
        if (sze[i] > sze[wson[cur]]) wson[cur] = i;
        fa[i] = cur;
    }
}
void dfs2(int cur, int lf) {
    lfa[cur] = lf;
    if (wson[cur]) dfs2(wson[cur], lf);
    for (auto i : son[cur]) if (i != wson[cur]) dfs2(i, i);
}
int lca(int u, int v) {
    while (lfa[u] != lfa[v]) {
        if (dep[lfa[u]] < dep[lfa[v]]) swap(u, v);
        u = fa[lfa[u]];
    }
    return dep[u] < dep[v] ? u : v;
}
matrix calc1_point(int p, int e) {
    matrix ans;
    if (U[e] == p) {
        ans[0][0] = {1, 0};
        ans[0][2] = W[e];
    }
    else {
        ans[0][1] = {1, 0};
        ans[0][3] = W[e];
    }
    return ans;
}
matrix calc1_edge(int e, int p) {
    matrix ans;
    if (U[e] == p) {
        ans[0][0] = {1, 0};
        ans[3][0] = {1, 0};
    }
    else {
        ans[1][0] = {1, 0};
        ans[2][0] = {1, 0};
    }
    return ans;
}
matrix calc2_edge(int e, int fae, int ee) {
    matrix ans;
    int tag1 = 0, tag2 = 0;
    if (V[e] == U[fae] || V[e] == V[fae]) tag1 = 1;
    if (U[e] == V[fae] || V[e] == V[fae]) tag2 = 1;
    ans[0 ^ tag1][0 ^ tag2] = {1, 0};
    ans[3 ^ tag1][0 ^ tag2] = {1, 0};
    ans[1 ^ tag1][1 ^ tag2] = W[ee];
    ans[2 ^ tag1][2 ^ tag2] = W[ee];
    return ans;
}
matrix calc2_point(int p, int fae, int e1, int e2) {
    matrix ans;
    if (U[e2] == U[fae] || V[e2] == U[fae]) swap(e1, e2);
    ans[0][0] = W[e1];
    ans[0][1] = W[e2];
    return ans;
}
matrix calc3_edge(int e, int fae, int ee) {
    matrix ans;
    int tag = 0;
    if (U[e] == V[fae]) tag = 1;
    ans[0][0] = {1, 0};
    ans[1][1] = {1, 0};
    ans[2][2] = {1, 0};
    ans[3][3] = {1, 0};
    ans[0][2] = W[ee];
    ans[1][3] = W[ee];
    return ans;
}
pair <int, int> qry[1000010];
int depl[1000010];
int sta[1280010];
matrix cursta[1280010];

void mult(node *a, const matrix &b) {
    node tmp[4];
    for (int i = 0; i < 4; i++) tmp[i] = a[i], a[i] = {0, 0};
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) a[j] += tmp[i] * b[i][j];
}
void modify(int x, int l, int r, int k, const matrix &v) {
    if (l == r) return t[x] = v, void();
    int mid = l + r >> 1;
    if (k <= mid) {
        modify(x << 1, l, mid, k, v);
    }
    else {
        modify(x << 1 | 1, mid + 1, r, k, v);
        if (k == r) t[x] = t[x << 1 | 1] * t[x << 1];
    }
}
void query(int x, int l, int r, int L, int R, int id) {
    if (L <= l && r <= R) {
        mult(ans[id], t[x]);
        return;
    }
    if (l > R || L > r) return;
    int mid = l + r >> 1;
    query(x << 1 | 1, mid + 1, r, L, R, id);
    query(x << 1, l, mid, L, R, id);
}

node mdfans[maxM];
void solve(int cur, int fa = 0) {
    if (cur <= n || fa == 0 || type[cur] == 1) {
        mdfans[cur] = {0, 0};
    }
    else if (type[cur] == 2) {
        mdfans[cur] = mdfans[fa] * W[keys[cur][0] + keys[cur][1]];
    }
    else if (type[cur] == 3) {
        mdfans[cur] = mdfans[fa] + W[keys[cur][0]];
    }

    if (dep[cur] % D == 1) cursta[dep[cur]] = a[cur];
    else cursta[dep[cur]] = a[cur] * cursta[dep[cur] - 1];
    sta[dep[cur]] = cur;
    if (dep[cur] % D == 0) modify(1, 1, maxd, dep[cur] / D, cursta[dep[cur]]);

    int pos = lower_bound(qry + 1, qry + 1 + 2 * q, make_pair(cur, 0)) - qry;
    while (qry[pos].first == cur) {
        int aid = qry[pos].second;
        ans[aid][0] = {1, 0};
        int L = depl[aid], R = dep[cur];
        while (R >= L && R % D != 0) {
            mult(ans[aid], a[sta[R--]]);
        }
        if (L <= R) {
            query(1, 1, maxd, (L + D - 1) / D + 1, R / D, aid);
            R = (L + D - 1) / D * D;
            assert(L <= R);
            while (R >= L) {
                mult(ans[aid], a[sta[R--]]);
            }
        }
        pnt[qry[pos].second] = sta[depl[qry[pos].second] - 1];
        pos++;
    }
    for (auto i : son[cur]) solve(i, cur);
}

int main() {
    freopen("simple.in", "r", stdin);
    freopen("simple.out", "w", stdout);
    I[0][0] = I[1][1] = I[2][2] = I[3][3] = {1, 0};
    scanf("%d%d%d", &n, &m, &q);
    cnt = n + m;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        out[u][v] = i + n;
        out[v][u] = i + n;
        U[i + n] = u, V[i + n] = v;
        W[i + n] = {1, w};
    }
    for (int i = 1; i <= n; i++) if (out[i].size() <= 2) {
        vis[i] = 1;
        que[++qcnt] = i;
    }
    for (int i = 1; i <= qcnt; i++) {
        int cur = que[i];
        if (out[cur].size() == 0) {
            rt = cur;
        }
        if (out[cur].size() == 1) {
            int v = out[cur].begin() -> first, id = out[cur].begin() -> second;
            out[v].erase(cur);

            son[v].push_back(id);
            son[id].push_back(cur);
            a[cur] = calc1_point(cur, id);
            a[id] = calc1_edge(id, v);
            type[cur] = type[id] = 1;

            if (!vis[v] && out[v].size() <= 2) {
                vis[v] = 1;
                que[++qcnt] = v;
            }
        }
        if (out[cur].size() == 2) {
            int u = out[cur].begin() -> first, v = (++out[cur].begin()) -> first;
            int idu = out[cur].begin() -> second, idv = (++out[cur].begin()) -> second;
            out[u].erase(cur), out[v].erase(cur);

            int id = ++cnt;
            W[id] = W[idu] * W[idv];
            U[id] = u, V[id] = v;
            son[id].push_back(idu);
            son[id].push_back(idv);
            son[id].push_back(cur);
            a[idu] = calc2_edge(idu, id, idv);
            a[idv] = calc2_edge(idv, id, idu);
            a[cur] = calc2_point(cur, id, idu, idv);
            type[idu] = type[idv] = type[cur] = 2;
            keys[cur][0] = idu;
            keys[cur][1] = idv;
            keys[idu][1] = idv;
            keys[idv][0] = idu;

            if (out[u].count(v)) {

                int newid = ++cnt, oldid = out[u][v];
                W[newid] = W[oldid] + W[id];
                U[newid] = u, V[newid] = v;
                son[newid].push_back(id);
                son[newid].push_back(oldid);
                a[id] = calc3_edge(id, newid, oldid);
                a[oldid] = calc3_edge(oldid, newid, id);
                type[id] = type[oldid] = 3;
                keys[id][0] = oldid;
                keys[oldid][0] = id;

                out[u][v] = out[v][u] = newid;
                if (!vis[u] && out[u].size() <= 2) {
                    vis[u] = 1;
                    que[++qcnt] = u;
                }
                if (!vis[v] && out[v].size() <= 2) {
                    vis[v] = 1;
                    que[++qcnt] = v;
                }
            }
            else {
                out[u][v] = out[v][u] = id;
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        map <int, int> tmp;
        tmp.swap(out[i]);
    }
    dep[rt] = 1;
    dfs(rt);
    dfs2(rt, rt);
    maxd = (maxd + D - 1) / D;
    for (int i = 1; i <= q; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        int l = lca(u, v);
        if (l <= n) {
            qry[i] = {u, i};
            qry[i + q] = {v, i + q};
            depl[i] = dep[l] + 1;
            depl[i + q] = dep[l] + 1;
        }
        else {
            qry[i] = {u, i};
            qry[i + q] = {v, i + q};
            depl[i] = dep[l] + 2;
            depl[i + q] = dep[l] + 2;
        }
    }
    sort(qry + 1, qry + 1 + 2 * q);
    solve(rt);
    for (int i = 1; i <= q; i++) {
        int u = pnt[i], v = pnt[i + q];
        if (u == v) {
            printf("%d\n", (ans[i][0] * ans[i + q][0]).b);
        }
        else {
            int l = fa[u];
            int u = pnt[i], v = pnt[i + q];
            node *ansu = ans[i], *ansv = ans[i + q];
            if (type[v] == 1 && v <= n) swap(u, v), swap(ansu, ansv);
            if (type[u] == 1 && u <= n) {
                mult(ansu, a[u]);
                mult(ansv, a[v]);
                node ans1 = ansu[0] * (ansv[0] + ansv[3]) + ansu[1] * (ansv[1] + ansv[2]);
                node ans2 = ansu[0] * ansv[1] + ansu[1] * ansv[0];
                printf("%d\n", (ans1 + ans2 * mdfans[l]).b);
                continue;
            }
            if (v <= n) swap(u, v), swap(ansu, ansv);
            if (u <= n) {
                node ans1, ans2;
                if (U[l] == U[v] || U[l] == V[v]) {
                    if (U[l] == U[v]) ans1 = ansv[1] + ansv[2], ans2 = ansv[0];
                    else ans1 = ansv[0] + ansv[3], ans2 = ansv[1];
                    ans1 = ans1 * ansu[0];
                    ans2 = ans2 * ansu[0] * W[keys[v][1]];
                }
                else {
                    if (V[l] == U[v]) ans1 = ansv[1] + ansv[2], ans2 = ansv[0];
                    else ans1 = ansv[0] + ansv[3], ans2 = ansv[1];
                    ans1 = ans1 * ansu[0];
                    ans2 = ans2 * ansu[0] * W[keys[v][0]];
                }
                printf("%d\n", (ans1 + ans2 * mdfans[l]).b);
                continue;
            }
            if (type[u] == 2) {
                if (keys[u][1] == 0) swap(u, v), swap(ansu, ansv);
                node ans1 = (U[u] == U[l] ? ansu[1] + ansu[2] : ansu[0] + ansu[3]) * (U[v] == V[l] ? ansv[1] + ansv[2] : ansv[0] + ansv[3]);
                node ans2 = (U[u] == U[l] ? ansu[0] : ansu[1]) * (U[v] == V[l] ? ansv[0] : ansv[1]);
                printf("%d\n", (ans1 + ans2 * mdfans[l]).b);
                continue;
            }
            if (type[u] == 3) {
                if (U[u] == V[v]) {
                    swap(ansu[0], ansu[1]);
                    swap(ansu[2], ansu[3]);
                }
                node ans1 = ansu[0] * (ansv[0] + ansv[3]) + ansu[3] * ansv[0];
                ans1 += ansu[1] * (ansv[1] + ansv[2]) + ansu[2] * ansv[1];
                node ans2 = ansu[0] * ansv[1] + ansu[1] * ansv[0];
                printf("%d\n", (ans1 + ans2 * mdfans[l]).b);
                continue;
            }
            puts("");
        }
    }
}