#include using namespace std; #define st first #define nd second #define PII pair const int N = 1e5 + 7; const int T = 1 << 17; int n, q; int ans[N]; int rep[N], roz[N]; stack S; map M; PII req[N]; vector tree[10][T + T + 7]; int Find(int a){ if(rep[a] == a) return a; return Find(rep[a]); } void Union(int u, int v){ int fu = Find(u), fv = Find(v); if(fu == fv){ S.push({-1, -1}); return; } if(roz[fu] > roz[fv]) swap(fu, fv); roz[fv] += roz[fu]; rep[fu] = fv; S.push({fu, fv}); } void rmv(){ PII t = S.top(); S.pop(); if(t.st == -1) return; rep[t.st] = t.st; roz[t.nd] -= roz[t.st]; } void add2(int w, int u, int v, int c){ for(int i = c; i < 10; ++i) tree[i][w].push_back({u, v}); } void add(int u, int v, int c, int s, int t){ s += T, t += T; while(s < t){ if(s & 1) add2(s, u, v, c); if(!(t & 1)) add2(t, u, v, c); s = (s + 1) / 2; t = (t - 1) / 2; } if(s == t) add2(s, u, v, c); } void go(int t, int u){ for(auto v: tree[t][u]) Union(v.st, v.nd); if(u >= T){ if(u > T && u <= q + T && req[u - T].nd != -1 && Find(req[u - T].st) == Find(req[u - T].nd)) ans[u - T] = t; } else{ go(t, u + u); go(t, u + u + 1); } for(auto v: tree[t][u]) rmv(); } int main(){ scanf("%d %d", &n, &q); for(int i = 1; i <= n; ++i) rep[i] = i, roz[i] = 1; for(int i = 1; i <= q; ++i){ ans[i] = -1; int t; scanf("%d", &t); if(t == 0){ int u, v, c; scanf("%d %d %d", &u, &v, &c); u++; v++; if(u > v) swap(u, v); req[i] = {c, -1}; M[{u, v}] = i; } if(t == 1){ int u, v; scanf("%d %d", &u, &v); u++; v++; if(u > v) swap(u, v); int from = M[{u, v}]; add(u, v, req[from].st, from, i); req[i] = {-1, -1}; M.erase({u, v}); } if(t == 2){ int u, v; scanf("%d %d", &u, &v); u++; v++; req[i] = {u, v}; } //puts("oki"); } for(auto v: M) add(v.st.st, v.st.nd, req[v.nd].st, v.nd, q + 1); //puts("ok1"); for(int i = 9; i >= 0; --i) go(i, 1); //puts("ok2"); for(int i = 1; i <= q; ++i) if(req[i].nd != -1) printf("%d\n", ans[i]); return 0; }