#include <bits/stdc++.h>
using namespace std;
vector<int> g[100001], edgesid[100001], dfs_list, lca_tree, edgeslist, tree1,
    tree2;
int x, type, z, ans, i, n, u, v, first[100001], m, first1[100001],
    first2[100001], h[100001];
void dfs(int v, int p = -1, int H = 0) {
  h[v] = H;
  dfs_list.push_back(v);
  for (int w = 0; w < g[v].size(); w++)
    if (h[g[v][w]] == -1) {
      edgeslist.push_back(edgesid[v][w]);
      dfs(g[v][w], v, H + 1);
      edgeslist.push_back(edgesid[v][w]);
      dfs_list.push_back(v);
    }
}
void build_lca_tree(int v, int l, int r) {
  if (l == r)
    lca_tree[v] = dfs_list[l];
  else {
    int m = (l + r) >> 1;
    build_lca_tree(v + v, l, m);
    build_lca_tree(v + v + 1, m + 1, r);
    int lt = lca_tree[v + v], rt = lca_tree[v + v + 1];
    lca_tree[v] = ((h[lt] < h[rt]) ? lt : rt);
  }
}
void prepare_lca() {
  lca_tree.assign(dfs_list.size() * 4, -1);
  build_lca_tree(1, 0, dfs_list.size() - 1);
  int i, v;
  for (i = 1; i <= n; i++) first[i] = -1;
  for (i = 0; i < dfs_list.size(); i++) {
    v = dfs_list[i];
    if (first[v] == -1) first[v] = i;
  }
}
void query_prepare() {
  int i, j;
  for (i = 1; i < n; i++) first1[i] = first2[i] = -1;
  for (i = 0; i < edgeslist.size(); i++) {
    j = edgeslist[i];
    if (first1[j] == -1)
      first1[j] = i;
    else
      first2[j] = i;
  }
  tree1.assign(edgeslist.size() * 4, 0);
  tree2.assign(edgeslist.size() * 4, 0);
}
int lca_query(int v, int tl, int tr, int l, int r) {
  if ((tl == l) && (tr == r)) return lca_tree[v];
  int tm = (tl + tr) >> 1;
  if (r <= tm) return lca_query(v + v, tl, tm, l, r);
  if (l > tm) return lca_query(v + v + 1, tm + 1, tr, l, r);
  int lt = lca_query(v + v, tl, tm, l, tm);
  int rt = lca_query(v + v + 1, tm + 1, tr, tm + 1, r);
  return ((h[lt] < h[rt]) ? lt : rt);
}
int calc_lca(int a, int b) {
  if (first[a] > first[b]) swap(a, b);
  return lca_query(1, 0, dfs_list.size() - 1, first[a], first[b]);
}
int sum_query(const vector<int>& tree, int v, int tl, int tr, int l, int r) {
  if ((l > r) || (tl > tr)) return 0;
  if ((tl == l) && (tr == r)) return tree[v];
  int tm = (tl + tr) >> 1;
  if (r <= tm) return sum_query(tree, v + v, tl, tm, l, r);
  if (l > tm) return sum_query(tree, v + v + 1, tm + 1, tr, l, r);
  int X = sum_query(tree, v + v, tl, tm, l, tm);
  int Y = sum_query(tree, v + v + 1, tm + 1, tr, tm + 1, r);
  return (X + Y);
}
int color_count(int v1, int v2) {
  int X =
      sum_query(tree1, 1, 0, edgeslist.size() - 1, first[v1], first[v2] - 1);
  int Y =
      sum_query(tree2, 1, 0, edgeslist.size() - 1, first[v1], first[v2] - 1);
  return (X - Y);
}
void edgestree_update(vector<int>& tree, int v, int tl, int tr, int p, int c) {
  if (tl == tr) {
    tree[v] = c;
    return;
  }
  int tm = (tl + tr) >> 1;
  if (p <= tm)
    edgestree_update(tree, v + v, tl, tm, p, c);
  else
    edgestree_update(tree, v + v + 1, tm + 1, tr, p, c);
  tree[v] = tree[v + v] + tree[v + v + 1];
}
int main() {
  scanf("%d", &n);
  for (i = 1; i < n; i++) {
    scanf("%d%d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u);
    edgesid[u].push_back(i);
    edgesid[v].push_back(i);
  }
  for (i = 1; i <= n; i++) h[i] = -1;
  edgeslist.clear();
  dfs_list.clear();
  dfs(1);
  prepare_lca();
  query_prepare();
  for (scanf("%d", &m); m; m--) {
    scanf("%d", &type);
    if (type == 3) {
      scanf("%d%d", &u, &v);
      z = calc_lca(u, v);
      ans = color_count(z, u) + color_count(z, v);
      if (ans == 0)
        ans = h[u] + h[v] - 2 * h[z];
      else
        ans = -1;
      printf("%d\n", ans);
    }
    if (type == 1) {
      scanf("%d", &x);
      edgestree_update(tree1, 1, 0, edgeslist.size() - 1, first1[x], 0);
      edgestree_update(tree2, 1, 0, edgeslist.size() - 1, first2[x], 0);
    }
    if (type == 2) {
      scanf("%d", &x);
      edgestree_update(tree1, 1, 0, edgeslist.size() - 1, first1[x], 1);
      edgestree_update(tree2, 1, 0, edgeslist.size() - 1, first2[x], 1);
    }
  }
  return 0;
}
