#include <bits/stdc++.h>
using namespace std;
class segment_tree {
 private:
  int _offset;
  vector<bool> _arr;
  bool has_path(int e1, int e2, int i, int l, int r) {
    if (e1 > r || e2 < l) {
      return true;
    }
    if (e1 <= l && e2 >= r) {
      return _arr[i];
    }
    int m = (l + r) / 2;
    return has_path(e1, e2, i * 2, l, m) &&
           has_path(e1, e2, i * 2 + 1, m + 1, r);
  }

 public:
  segment_tree(int n) {
    int k(1);
    while (k < n) {
      k <<= 1;
    }
    _offset = k;
    _arr.resize(k * 2, true);
  }
  void update(int i, int e) {
    i += _offset;
    _arr[i] = e;
    i = i >> 1;
    while (i > 0) {
      _arr[i] = _arr[i * 2] && _arr[i * 2 + 1];
      i = i >> 1;
    }
  }
  int get_path_length(int v1, int v2) {
    if (v1 == v2) {
      return 0;
    }
    int e1(0), e2(0);
    if (v1 > v2) {
      e1 = v2;
      e2 = v1 - 1;
    } else {
      e1 = v1;
      e2 = v2 - 1;
    }
    if (!has_path(e1 + _offset, e2 + _offset, 1, _offset, _offset * 2 - 1)) {
      return -1;
    }
    return e2 - e1 + 1;
  }
};
vector<segment_tree> seg_trees;
vector<pair<int, int>> edges;
vector<pair<int, int>> vertices;
void build_seg_tree(int n, const vector<vector<pair<int, int>>> &graph, int v) {
  edges.resize(n);
  vertices.resize(n + 1);
  vertices[v].first = -1;
  vertices[v].second = 0;
  vector<bool> used;
  queue<int> q;
  for (int i = 0; i < graph[v].size(); i++) {
    int k(0);
    used.assign(n + 1, false);
    used[v] = true;
    q.push(graph[v][i].first);
    edges[graph[v][i].second].first = i;
    edges[graph[v][i].second].second = k;
    while (!q.empty()) {
      int c = q.front();
      used[c] = true;
      vertices[c].first = i;
      vertices[c].second = k + 1;
      q.pop();
      for (int j = 0; j < graph[c].size(); j++) {
        if (!used[graph[c][j].first]) {
          q.push(graph[c][j].first);
          k++;
          edges[graph[c][j].second].first = i;
          edges[graph[c][j].second].second = k;
        }
      }
    }
    seg_trees.push_back(segment_tree(k + 1));
  }
}
void read_graph() {
  int n;
  cin >> n;
  vector<vector<pair<int, int>>> graph(n + 1, vector<pair<int, int>>(0));
  for (int i = 1; i < n; i++) {
    int v1, v2;
    cin >> v1 >> v2;
    graph[v1].push_back(pair<int, int>(v2, i));
    graph[v2].push_back(pair<int, int>(v1, i));
  }
  int v(1);
  for (int i = 1; i <= n; i++) {
    if (graph[i].size() > graph[v].size()) {
      v = i;
    }
  }
  build_seg_tree(n, graph, v);
}
void paint_edge(int e, int c) {
  seg_trees[edges[e].first].update(edges[e].second, c);
}
void find_path(int v1, int v2) {
  if (v1 == v2) {
    cout << 0 << endl;
    return;
  }
  if (vertices[v1].second == 0 && vertices[v2].second == 0) {
    cout << -2 << endl;
    return;
  }
  int t1 = vertices[v1].first;
  int t2 = vertices[v2].first;
  if (vertices[v1].second == 0) {
    t1 = t2;
  }
  if (vertices[v2].second == 0) {
    t2 = t1;
  }
  int result(0);
  if (t1 == t2) {
    result =
        seg_trees[t1].get_path_length(vertices[v1].second, vertices[v2].second);
  } else {
    int l1 = seg_trees[t1].get_path_length(0, vertices[v1].second);
    int l2 = seg_trees[t2].get_path_length(0, vertices[v2].second);
    if (l1 == -1 || l2 == -1) {
      result = -1;
    } else {
      result = l1 + l2;
    }
  }
  if (result == 0) {
    result = -3;
  }
  cout << result << endl;
}
void read_and_process() {
  int m;
  cin >> m;
  for (int i = 0; i < m; i++) {
    int t, e, v1, v2;
    cin >> t;
    switch (t) {
      case 1:
        cin >> e;
        paint_edge(e, 1);
        break;
      case 2:
        cin >> e;
        paint_edge(e, 0);
        break;
      case 3:
        cin >> v1 >> v2;
        find_path(v1, v2);
        break;
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  read_graph();
  read_and_process();
  return 0;
}
