#include <bits/stdc++.h>   using namespace std;   const int inf = 100010;   const int N = 100010;   struct e {     int v;     e *nxt;   } es[N << 1], *fir[N];   map<pair<int, int>, int> mp;   struct node {     int ls, rs;     int l, r;     int sum;     int mid() { return (l + r) >> 1; }   } nodes[N << 2];   int n, en, val[N];   int que[N], par[N], dep[N], root[N], seg[N], st[N], ed[N], top[N], sons[N],       id[N];   int ln, cnt, tr;   inline void init() {     en = 0;     memset(fir, 0, sizeof(fir));   }   inline void add_e(int u, int v) {     es[en].v = v;     es[en].nxt = fir[u];     fir[u] = &es[en++];   }   inline void newNode(int &id, int l, int r) {     nodes[cnt].ls = nodes[cnt].rs = -1;     nodes[cnt].l = l;     nodes[cnt].r = r;     id = cnt++;   }   void build(int &id, int l, int r) {     newNode(id, l, r);     if (l + 1 >= r) {       nodes[id].sum = 1;       return;     }     int mid = (l + r) >> 1;     build(nodes[id].ls, l, mid);     build(nodes[id].rs, mid, r);     nodes[id].sum = nodes[nodes[id].ls].sum + nodes[nodes[id].rs].sum;   }   void initTree() {     int l, r, u, v, i;     e *cur;     l = r = 0;     tr = 1;     que[r++] = tr;     par[tr] = -1;     dep[tr] = 0;     while (l != r) {       u = que[l++];       for (cur = fir[u]; cur; cur = cur->nxt) {         if ((v = cur->v) != par[u]) {           que[r++] = v;           par[v] = u;           dep[v] = dep[u] + 1;         }       }     }     for (i = 1; i <= n; i++) {       sons[i] = 1;       id[i] = -1;     }     for (i = r - 1; i >= 0; i--) {       u = que[i];       if (par[u] >= 0) {         sons[par[u]] += sons[u];       }     }     l = r = 0;     que[r++] = tr;     ln = cnt = 0;     while (l != r) {       u = que[l++];       st[ln] = dep[u];       top[ln] = u;       while (u >= 0) {         id[u] = ln;         ed[ln] = dep[u];         seg[dep[u]] = u;         int best;         for (cur = fir[u], best = -1; cur; cur = cur->nxt) {           if (id[v = cur->v] == -1) {             if (best == -1 || (best >= 0 && sons[v] > sons[best])) {               best = v;             }           }         }         if (best >= 0) {           for (cur = fir[u]; cur; cur = cur->nxt) {             if (id[v = cur->v] == -1 && best != v) {               que[r++] = v;             }           }         }         u = best;       }       root[ln] = -1;       build(root[ln], st[ln], ed[ln]);       ln++;     }   }   int S;   void lqry(int &id, int ql, int qr) {     if (id == -1) return;     if (ql == qr) return;     if (ql <= nodes[id].l && nodes[id].r <= qr) {       S += nodes[id].sum;       if (S > inf) S = inf;       return;     }     if (nodes[id].l + 1 == nodes[id].r) {       S += nodes[id].sum;       if (S > inf) S = inf;       return;     }     int mid = (nodes[id].l + nodes[id].r) >> 1;     if (ql < mid) {       lqry(nodes[id].ls, ql, qr);     }     if (qr > mid) {       lqry(nodes[id].rs, ql, qr);     }   }   void update(int id, int x, int y, int val) {     if (id == -1) return;     if (nodes[id].l + 1 == nodes[id].r) {       nodes[id].sum = val;       return;     }     int mid = (nodes[id].l + nodes[id].r) >> 1;     if (mid <= x)       update(nodes[id].rs, x, y, val);     else if (mid >= y)       update(nodes[id].ls, x, y, val);     nodes[id].sum = nodes[nodes[id].ls].sum + nodes[nodes[id].rs].sum;     if (nodes[id].sum > inf) nodes[id].sum = inf;   }   void qry(int u, int v) {     while (id[u] != id[v]) {       if (id[u] > id[v]) {         swap(u, v);       }       int b = id[v];       lqry(root[b], st[b], dep[v]);       v = par[top[b]];       if (mp.find(make_pair(top[b], par[top[b]])) != mp.end())         S += val[mp[make_pair(top[b], par[top[b]])]];       else         S += val[mp[make_pair(par[top[b]], top[b])]];       if (S > inf) S = inf;     }     if (dep[u] > dep[v]) {       swap(u, v);     }     lqry(root[id[u]], dep[u], dep[v]);   }   struct ee {     int x, y;   } edge[100010];   int main() {     int m, x, y, ty;     scanf( %d , &n);     init();     for (int i = 1; i < n; i++) {       scanf( %d%d , &x, &y);       mp[make_pair(x, y)] = i;       val[i] = 1;       edge[i].x = x;       edge[i].y = y;       add_e(x, y);       add_e(y, x);     }     initTree();     scanf( %d , &m);     for (int i = 0; i < m; i++) {       scanf( %d , &ty);       if (ty == 3) {         scanf( %d%d , &x, &y);         S = 0;         qry(x, y);         if (S >= inf)           printf( -1 n );         else           printf( %d n , S);       } else if (ty == 1) {         scanf( %d , &x);         int u = edge[x].x;         int v = edge[x].y;         val[x] = 1;         if (dep[u] > dep[v]) {           swap(u, v);         }         if (id[u] == id[v]) update(root[id[u]], dep[u], dep[u], 1);       } else {         scanf( %d , &x);         int u = edge[x].x;         int v = edge[x].y;         val[x] = inf;         if (dep[u] > dep[v]) {           swap(u, v);         }         if (id[u] == id[v]) update(root[id[u]], dep[u], dep[v], inf);       }     }   }   