#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000 * 100 + 100;
int n, m, cmp_cnt;
int cmp[MAXN], ccmp[MAXN], mark[MAXN];
int edge[MAXN][2];
vector<int> adj[MAXN];
void dfs(int u, int deep) {
  mark[u] = deep;
  cmp[u] = cmp_cnt;
  ccmp[cmp_cnt]++;
  for (int i = 0; i < adj[u].size(); i++)
    if (mark[adj[u][i]] == 0) dfs(adj[u][i], deep + 1);
}
struct node {
  int s, e, value;
  node *left;
  node *right;
  node() {
    s = e = -1;
    value = 0;
    left = right = NULL;
  }
  void make(int ss, int ee) {
    s = ss;
    e = ee;
  }
} tree[MAXN];
void add(int p, node *v, int step) {
  if (p < (v->s) or p > (v->e)) return;
  (v->value) += step;
  if ((v->e) == (v->s)) return;
  int mid = ((v->s) + (v->e)) / 2;
  if (p <= mid) {
    if ((v->left) == NULL) {
      v->left = new node;
      (v->left)->make((v->s), mid);
    }
    add(p, v->left, step);
  } else {
    if ((v->right) == NULL) {
      v->right = new node;
      (v->right)->make(mid + 1, (v->e));
    }
    add(p, v->right, step);
  }
}
int find(int s, int e, node *v) {
  if (s > (v->e) or e < (v->s)) return 0;
  if (s <= (v->s) and (v->e) <= e) return (v->value);
  int res = 0;
  if ((v->left) != NULL) res += find(s, e, v->left);
  if ((v->right) != NULL) res += find(s, e, v->right);
  return res;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin >> n;
  int root = 1;
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    cin >> a >> b;
    adj[a].push_back(b);
    adj[b].push_back(a);
    edge[i][0] = a;
    edge[i][1] = b;
  }
  for (int i = 1; i <= n; i++)
    if (adj[i].size() > adj[root].size()) root = i;
  mark[root] = 1;
  for (int i = 0; i < adj[root].size(); i++) {
    int u = adj[root][i];
    cmp_cnt++;
    dfs(u, 2);
    tree[cmp_cnt].make(0, ccmp[cmp_cnt]);
  }
  cin >> m;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a;
    if (a == 1) {
      cin >> b;
      int u = edge[b - 1][0];
      int v = edge[b - 1][1];
      int D = min(mark[u], mark[v]);
      int C = max(cmp[u], cmp[v]);
      add(D, &tree[C], -1);
    } else if (a == 2) {
      cin >> b;
      int u = edge[b - 1][0];
      int v = edge[b - 1][1];
      int D = min(mark[u], mark[v]);
      int C = max(cmp[u], cmp[v]);
      add(D, &tree[C], +1);
    } else {
      cin >> b >> c;
      if (b == c)
        cout << 0 << endl;
      else if (cmp[b] == cmp[c] or (b == root or c == root)) {
        int C = max(cmp[c], cmp[b]);
        if (mark[b] > mark[c]) swap(b, c);
        int D = find(mark[b], mark[c] - 1, &tree[C]);
        if (D != 0)
          cout << -1 << endl;
        else
          cout << mark[c] - mark[b] << endl;
      } else {
        int D = find(1, mark[b] - 1, &tree[cmp[b]]);
        int DD = find(1, mark[c] - 1, &tree[cmp[c]]);
        if (D != 0 or DD != 0)
          cout << -1 << endl;
        else
          cout << mark[b] + mark[c] - 2 << endl;
      }
    }
  }
  return 0;
}
