#include <bits/stdc++.h>
template <typename T>
inline void read(T &x) {
  T sum = 0, sign = 1;
  char c = getchar();
  while (!((c) >= '0' && (c) <= '9')) {
    if (c == '-') sign = -1;
    c = getchar();
  }
  while (((c) >= '0' && (c) <= '9')) {
    sum = (sum << 1) + (sum << 3) + c - '0';
    c = getchar();
  }
  x = sum * sign;
}
template <typename T>
inline T max(T a, T b) {
  return a > b ? a : b;
}
template <typename T>
inline T min(T a, T b) {
  return a < b ? a : b;
}
const int N = 1e5 + 50, M = N << 2;
int n, m;
class Segment_Tree {
 private:
  int lc[M], rc[M], tot = 0;
  int node_sum[M], node_white[M];

 public:
  int root = 0;

 private:
  inline int add_node() {
    ++tot;
    lc[tot] = rc[tot] = 0;
    node_sum[tot] = 0;
    node_white[tot] = 0;
    return tot;
  }
  inline void push_up(int rt) {
    node_sum[rt] = node_sum[lc[rt]] + node_sum[rc[rt]];
    node_white[rt] = node_white[lc[rt]] | node_white[rc[rt]];
  }

 public:
  inline void build(int &rt, int l, int r) {
    if (!rt) rt = add_node();
    if (l == r) {
      node_sum[rt] = 1, node_white[rt] = 0;
      return;
    }
    int mid = l + r >> 1;
    build(lc[rt], l, mid);
    build(rc[rt], mid + 1, r);
    push_up(rt);
  }
  inline void modify_node(int rt, int l, int r, int pos, int k) {
    if (l == r) {
      node_sum[rt] = k ^ 1;
      node_white[rt] = k;
      return;
    }
    int mid = l + r >> 1;
    if (mid >= pos) modify_node(lc[rt], l, mid, pos, k);
    if (mid + 1 <= pos) modify_node(rc[rt], mid + 1, r, pos, k);
    push_up(rt);
  }
  inline int query_sum(int rt, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) {
      if (node_white[rt]) return -1;
      return node_sum[rt];
    }
    int mid = l + r >> 1;
    int res = 0;
    if (mid >= ql) {
      int tmp = query_sum(lc[rt], l, mid, ql, qr);
      if (tmp == -1) return -1;
      res += tmp;
    }
    if (mid + 1 <= qr) {
      int tmp = query_sum(rc[rt], mid + 1, r, ql, qr);
      if (tmp == -1) return -1;
      res += tmp;
    }
    return res;
  }
} tr;
class Tree {
 public:
  class Directed_Edge {
   public:
    int nxt, to;
  } edge[N << 1];
  int head[N];
  inline void add_directed_edge(int u, int v) {
    static int tot = 0;
    ++tot;
    edge[tot].nxt = head[u];
    edge[tot].to = v;
    head[u] = tot;
  }
  inline void add_edge(int u, int v) {
    add_directed_edge(u, v), add_directed_edge(v, u);
  }
  int fa[N], dep[N], size[N], son[N], top[N], id[N], cnt = 0;
  inline void dfs1(int u, int f) {
    fa[u] = f;
    dep[u] = dep[f] + 1;
    size[u] = 1;
    for (int i = head[u]; i; i = edge[i].nxt) {
      int v = edge[i].to;
      if (v == f) continue;
      dfs1(v, u);
      size[u] += size[v];
      if (size[v] > size[son[u]]) son[u] = v;
    }
  }
  inline void dfs2(int u, int Top) {
    top[u] = Top;
    id[u] = ++cnt;
    if (!son[u]) return;
    dfs2(son[u], Top);
    for (int i = head[u]; i; i = edge[i].nxt) {
      int v = edge[i].to;
      if (v == fa[u] || v == son[u]) continue;
      dfs2(v, v);
    }
  }
  inline void modify_edge(int u, int v, int k) {
    if (dep[u] < dep[v]) std::swap(u, v);
    tr.modify_node(tr.root, 1, n, id[u], k);
  }
  inline int query_path_sum_edge(int u, int v) {
    int res = 0;
    while (top[u] != top[v]) {
      if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
      int tmp = tr.query_sum(tr.root, 1, n, id[top[u]], id[u]);
      if (tmp == -1) return -1;
      res += tmp;
      u = fa[top[u]];
    }
    if (dep[u] < dep[v]) std::swap(u, v);
    int tmp = tr.query_sum(tr.root, 1, n, id[v] + 1, id[u]);
    if (tmp == -1) return -1;
    res += tmp;
    return res;
  }
} tree;
class Edge {
 public:
  int u, v;
} edge[N];
inline void init() {}
inline void solve() {
  init();
  read(n);
  for (int u, v, i = 1; i < n; ++i) {
    read(u), read(v);
    edge[i].u = u, edge[i].v = v;
    tree.add_edge(u, v);
  }
  tree.dfs1(1, 0), tree.dfs2(1, 1);
  tr.build(tr.root, 1, n);
  read(m);
  for (int opt, i = 1; i <= m; ++i) {
    read(opt);
    if (opt == 1) {
      int u;
      read(u);
      tree.modify_edge(edge[u].u, edge[u].v, 0);
    }
    if (opt == 2) {
      int u;
      read(u);
      tree.modify_edge(edge[u].u, edge[u].v, 1);
    }
    if (opt == 3) {
      int u, v;
      read(u), read(v);
      printf("%d\n", tree.query_path_sum_edge(u, v));
    }
  }
  return;
}
int test;
int main() {
  test = 1;
  for (int i = 1; i <= test; ++i) solve();
  return 0;
}
