#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e6 + 7;
const int mod = 998244353;
int n1, n2;
int h;
int add(int a, int b) { return a + b >= mod ? a + b - mod : a + b; }
int sub(int a, int b) { return a >= b ? a - b : a - b + mod; }
int mul(int a, int b) { return 1ll * a * b % mod; }
int qpow(int x)
{
    int ans = 1, two = 2;
    while (x)
    {
        if (x & 1) ans = mul(ans, two);
        two = mul(two, two);
        x >>= 1;
    }
    return ans;
}
class Mygraph
{
private:
    Mygraph() {};
public:
    static deque<pii> dq[maxn];
    static int qcnt;
    static void push_back(int d, int e, int& c)
    {
        if (d >= qcnt) return;
        int tmp = dq[d].back().first ^ 1;
        if (tmp) c = add(c, qpow(e));
        dq[d].push_back(make_pair(tmp, e));
    }
    static void push_front(int d, int e, int& c)
    {
        if (d >= qcnt) return;
        int tmp = dq[d].front().first ^ 1;
        if (tmp) c = add(c, qpow(e));
        dq[d].push_front(make_pair(tmp, e));
    }
    static void reverse(int d)
    {
        stack<pii> s;
        while (!dq[d].empty())
        {
            s.push(dq[d].front());
            dq[d].pop_front();
        }
        while (!s.empty())
        {
            dq[d].push_back(s.top());
            s.pop();
        }
    }
};
struct path
{
    int s, t, d, c;
    path() {};
    path(int s, int t, int d, int c) : s(s), t(t), d(d), c(c) {};
    void push_front(int e) { Mygraph::push_front(d, e, c); }
    void push_back(int e) { Mygraph::push_back(d, e, c); }
    void pop_front() { Mygraph::dq[d].pop_front(); }
    void pop_back() { Mygraph::dq[d].pop_back(); }
    int front() { return Mygraph::dq[d].front().second; }
    int back() { return Mygraph::dq[d].back().second; }
    void reverse() { Mygraph::reverse(d); swap(s, t); }
    bool empty() { return Mygraph::dq[d].empty(); }
    bool size() { return Mygraph::dq[d].size(); }
};
class Mypath
{
private:
    Mypath() {};
public:
    static vector<int> vertex[maxn];
    static set<int> paths_set;
    static path paths[maxn];
    static int pcnt;
    static int ecnt;
    static path cat_to_ab(path a, path b)
    {
        path ans = a;
        while (!b.empty())
        {
            ans.push_back(b.front());
            b.pop_front();
        }
        ans.t = b.t;
        return ans;
    }
    static path cat_to_ba(path a, path b)
    {
        path ans = a;
        while (!b.empty())
        {
            ans.push_front(b.back());
            b.pop_back();
        }
        ans.s = b.s;
        return ans;
    }
public:

    static path create_path(int u, int v)
    {
        Mygraph::dq[Mygraph::qcnt].push_back(make_pair(0, ecnt++));
        return path(u, v, Mygraph::qcnt++, 0);
    }
    static path cat_path(path a, path b, int v)
    {
        if (a.size() < b.size()) swap(a, b);
        if (a.s == v)
        {
            if (b.t != v) b.reverse();
            return cat_to_ba(a, b);
        }
        else
        {
            if (b.s != v) b.reverse();
            return cat_to_ab(a, b);
        }
    }
    static void merge_path(int a, int b, int v)
    {
        if (a == b) return;
        h = sub(h, paths[a].c);
        h = sub(h, paths[b].c);
        paths[pcnt] = cat_path(paths[a], paths[b], v);
        paths_set.erase(a);
        paths_set.erase(b);
        paths_set.insert(pcnt);
        for (int& i : vertex[paths[a].s]) if (i == a || i == b) i = pcnt;
        for (int& i : vertex[paths[a].t]) if (i == a || i == b) i = pcnt;
        for (int& i : vertex[paths[b].s]) if (i == a || i == b) i = pcnt;
        for (int& i : vertex[paths[b].t]) if (i == a || i == b) i = pcnt;
        h = add(h, paths[pcnt++].c);
    }
    static void compressed(int v)
    {
        while (vertex[v].size() >= 2)
        {
            int a = vertex[v].back(); vertex[v].pop_back();
            int b = vertex[v].back(); vertex[v].pop_back();
            merge_path(a, b, v);
        }
    }
    static void add_edge(int u, int v)
    {
        paths[pcnt] = create_path(u, v);
        vertex[u].push_back(pcnt);
        vertex[v].push_back(pcnt);
        paths_set.insert(pcnt++);
        compressed(u);
        compressed(v);
    }
    static void print_red()
    {
        vector<int> ans;
        for (int p : paths_set)
        {
            for (pii tmp : Mygraph::dq[paths[p].d])
            {
                if (tmp.first == 1)
                {
                    ans.push_back(tmp.second);
                }
            }
        }
        printf("%d", ans.size());
        for (int i : ans) printf(" %d", i);
        printf("\n");
    }
};
deque<pii>  Mygraph::dq[maxn];
int         Mygraph::qcnt;
vector<int> Mypath::vertex[maxn];
set<int>    Mypath::paths_set;
path        Mypath::paths[maxn];
int         Mypath::pcnt;
int         Mypath::ecnt = 1;
int main()
{
    int m;
    scanf("%d %d %d", &n1, &n2, &m);
    while (m--)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        v += 200000;
        Mypath::add_edge(u, v);
    }
    int q;
    scanf("%d", &q);
    while (q--)
    {
        int op;
        scanf("%d", &op);
        if (op == 1)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            v += 200000;
            Mypath::add_edge(u, v);
            printf("%d\n", h);
        }
        else if (op == 2)
        {
            Mypath::print_red();
        }
        fflush(stdout);
//        printf("vertex:\n");
//        printf("==============================\n");
//        for (int i = 0; i < maxn; ++i)
//        {
//            if (Mypath::vertex[i].size())
//            {
//                printf("|");
//                printf("%d:", i);
//                for (int j : Mypath::vertex[i])
//                {
//                    printf(" %d", j);
//                }
//                printf("\n");
//            }
//        }
//        printf("=============================\n");
//        printf("path:\n");
//        printf("-----------------------------\n");
//        for (int p : Mypath::paths_set)
//        {
//            printf("|%d:", p);
//            for (pii tmp : Mygraph::dq[Mypath::paths[p].d])
//            {
//                printf("--(%d, %d)", tmp.first, tmp.second);
//            }
//            printf("\n");
//        }
//        printf("-----------------------------\n");
    }
}
