#include using namespace std; struct treap { treap *lc, *rc, *fa; int val, sz, pri; treap() = default; treap(int v) : val(v), lc(nullptr), rc(nullptr), pri(rand()), sz(1), fa(nullptr) {} void pull() { sz = 1; if (lc) sz += lc->sz, lc->fa = this; if (rc) sz += rc->sz, rc->fa = this; } }; treap *merge(treap *a, treap *b) { if (!a || !b) return a ? a : b; if (a->pri > b->pri) return a->rc = merge(a->rc, b), a->pull(), a; else return b->lc = merge(a, b->lc), b->pull(), b; } void split_by_val(treap *t, int k, treap *&a, treap *&b) { if (!t) return a = b = nullptr, void(); if (t->val <= k) a = t, split_by_val(t->rc, k, a->rc, b), a->pull(); else b = t, split_by_val(t->lc, k, a, b->lc), b->pull(); } void split_by_sz(treap *t, int k, treap *&a, treap *&b) { if (!t) return a = b = nullptr, void(); int lsz = (t->lc ? t->lc->sz : 0) + 1; if (lsz <= k) a = t, split_by_sz(t->rc, k - lsz, a->rc, b), a->pull(); else b = t, split_by_sz(t->lc, k, a, b->lc), b->pull(); } const int maxn = 1e5 + 5; int fa[maxn][20], dep[maxn]; vector g[maxn]; bool mdf[maxn]; treap *tr[maxn]; treap pool[maxn]; int lca(int x, int y) { if (dep[x] > dep[y]) swap(x, y); for (int i = 19; i >= 0; --i) { if ((dep[y] - dep[x]) >> i & 1) y = fa[y][i]; } if (x == y) return x; for (int i = 19; i >= 0; --i) { if (fa[x][i] != fa[y][i]) { x = fa[x][i]; y = fa[y][i]; } } return fa[x][0]; } int dist(int x, int y) { return dep[x] + dep[y] - 2 * dep[lca(x, y)]; } void predfs(int x, int p) { fa[x][0] = p; dep[x] = ~p ? dep[p] + 1 : 0; for (int i = 1; i < 20; ++i) fa[x][i] = -1; for (int i = 1; (1 << i) <= dep[x]; ++i) fa[x][i] = fa[fa[x][i - 1]][i - 1]; for (int u : g[x]) { if (u != p) predfs(u, x); } } treap *insert(treap *x, treap *y) { assert(y && y->sz == 1); treap *lz, *rz; split_by_val(x, y->val, lz, rz); if (lz) lz->fa = nullptr; if (rz) rz->fa = nullptr; return merge(merge(lz, y), rz); } treap *unite(treap *x, treap *y) { if (!x || !y) return x ? x : y; if (x->sz < y->sz) swap(x, y); while (y) { treap *lz, *rz; split_by_sz(y, 1, lz, rz); if (lz) lz->fa = nullptr; if (rz) rz->fa = nullptr; y = rz; x = insert(x, lz); } return x; } treap *root(treap *z) { while (z->fa) z = z->fa; return z; } treap *dfs(int x) { // printf("x = %d\n", x); if (mdf[x]) return root(tr[x]); mdf[x] = true; treap *z = tr[x]; for (int u : g[x]) { if (u != fa[x][0]) { treap *p = dfs(u); z = unite(z, p); } } return z; } int position(treap *t) { int res = t->lc ? t->lc->sz : 0; while (t->fa) { if (t->fa->rc == t) res += 1 + (t->fa->lc ? t->fa->lc->sz : 0); t = t->fa; } return t->sz - 1 - res; } int rightmost(treap *z) { while (z->rc) z = z->rc; return z->val; } void debug(treap *z) { if (z->lc) debug(z->lc); printf("%d ", z->val); if (z->rc) debug(z->rc); } int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); int ptr = 0; for (int i = 0; i < n; ++i) g[i].clear(); for (int i = 0; i < n; ++i) mdf[i] = false; for (int i = 0; i < n; ++i) tr[i] = new (&pool[ptr++]) treap(i); for (int i = 0; i < n - 1; ++i) { int u, v; scanf("%d%d", &u, &v); --u, --v; g[u].push_back(v); g[v].push_back(u); } predfs(0, -1); int q; scanf("%d", &q); while (q--) { int z; scanf("%d", &z); if (z == 1) { int x; scanf("%d", &x); --x; if (mdf[x]) continue; treap *z = dfs(x); // printf("debug(z)\n"); // debug(z); // puts(""); int v = rightmost(z); // printf("v = %d\n", v); dep[v] = dep[x]; for (int i = 0; i < 20; ++i) fa[v][i] = fa[x][i]; } else { int x, y; scanf("%d%d", &x, &y); --x, --y; int rx = position(tr[x]), ry = position(tr[y]); // printf("rx = %d ry = %d\n", rx, ry); if (root(tr[x]) == root(tr[y])) { printf("%d\n", abs(rx - ry)); } else { int vx = rightmost(root(tr[x])); int vy = rightmost(root(tr[y])); printf("%d\n", rx + ry + dist(vx, vy)); } } } } return 0; }