#include <bits/stdc++.h>   using namespace std;   const int N = 1 << 18;   int uf[N];   int cost[N];   vector<pair<int, int>> h_uf;   vector<pair<int, int>> h_cost;   pair<int, int> query[N];   int ans[N];   bool sample;   struct edge {     int u, v, w;     edge(int u, int v, int w) : u(u), v(v), w(w) {}   };   vector<edge> seg[N * 2];   int find(int u) {     while (uf[u] >= 0) {       u = uf[u];     }     return u;   }   int find_cost(int u) {     int res = 0;     while (uf[u] >= 0) {       res ^= cost[u];       u = uf[u];     }     return res;   }   bool unite(int u, int v, int w) {     int pu = find(u);     int pv = find(v);     if (pu == pv) return false;     w ^= find_cost(u);     w ^= find_cost(v);     u = pu;     v = pv;     if (-uf[u] < -uf[v]) swap(u, v);     h_uf.emplace_back(u, uf[u]);     h_uf.emplace_back(v, uf[v]);     h_cost.emplace_back(v, cost[v]);     uf[u] += uf[v];     uf[v] = u;     cost[v] = w;     return true;   }   void undo() {     auto p = h_uf.back();     h_uf.pop_back();     auto q = h_uf.back();     h_uf.pop_back();     auto r = h_cost.back();     h_cost.pop_back();     uf[p.first] = p.second;     uf[q.first] = q.second;     cost[r.first] = r.second;   }   int find_cost(int u, int v) { return find_cost(u) ^ find_cost(v); }   void init_uf(int n) {     for (int i = 0; i < n; i++) {       uf[i] = -1;     }   }   void insert(int l, int r, edge e, int k = 1, int ll = 0, int rr = N) {     if (rr <= l || r <= ll) return;     if (l <= ll && rr <= r) {       seg[k].emplace_back(e);       return;     }     insert(l, r, e, k * 2 + 0, ll, ll + rr >> 1);     insert(l, r, e, k * 2 + 1, ll + rr >> 1, rr);   }   vector<int> normalize(vector<int> a) {     int r = 0;     for (int j = 29; j >= 0; j--) {       int p = -1;       for (int i = r; i < a.size(); i++) {         if (a[i] >> j & 1) {           p = i;           break;         }       }       if (p == -1) continue;       swap(a[r], a[p]);       for (int i = r + 1; i < a.size(); i++) {         if (a[i] >> j & 1) {           a[i] ^= a[r];         }       }       r++;     }     a.resize(r);     return a;   }   int find_min(int x, vector<int> &a) {     for (int y : a) x = min(x, x ^ y);     return x;   }   void dfs(vector<int> a, int k = 1, int l = 0, int r = N) {     int cnt = 0;     for (edge e : seg[k]) {       if (unite(e.u, e.v, e.w)) {         cnt++;       } else {         a.push_back(e.w ^ find_cost(e.u, e.v));       }     }     a = normalize(a);     if (r - l == 1) {       if (query[l].second != 0) {         ans[l] = find_min(find_cost(query[l].first, query[l].second), a);       }       return;     }     dfs(a, k * 2 + 0, l, l + r >> 1);     dfs(a, k * 2 + 1, l + r >> 1, r);     while (cnt--) undo();   }   int input() {     int n;     scanf( %d , &n);     return n;   }   int main() {     int n, m;     cin >> n >> m;     init_uf(n);     map<pair<int, int>, pair<int, int>> mp;     for (int i = 0; i < m; i++) {       int u = input() - 1;       int v = input() - 1;       int w = input();       mp[{u, v}] = {w, 0};     }     int q = input();     for (int i = 1; i <= q; i++) {       int type = input();       int u = input() - 1;       int v = input() - 1;       if (type == 1) {         int w = input();         mp[{u, v}] = {w, i};       } else if (type == 2) {         auto it = mp.find({u, v});         insert(it->second.second, i, edge(u, v, it->second.first));         mp.erase(it);       } else {         query[i] = {u, v};       }     }     for (auto p : mp) {       int u = p.first.first;       int v = p.first.second;       int w = p.second.first;       int s = p.second.second;       insert(s, q + 1, edge(u, v, w));     }     sample = n <= 10;     dfs({});     for (int i = 1; i <= q; i++) {       if (query[i].second != 0) {         printf( %d n , ans[i]);       }     }   }