#include using namespace std; const int MAXN = (int) 1e5 + 5; int n; namespace SegTree { bool val[MAXN << 2]; void init() { memset(val, 0, sizeof val); } void modify(int k, int l, int r, int ql, int qr) { if (ql <= l && r <= qr) { val[k] = true; return; } if (val[k]) { return; } int mid = (l + r) >> 1; if (ql <= mid) { modify(k << 1, l, mid, ql, qr); } if (mid < qr) { modify(k << 1 | 1, mid + 1, r, ql, qr); } } bool query(int k, int l, int r, int p) { if (val[k]) { return true; } if (l == r) { return false; } int mid = (l + r) >> 1; if (p <= mid) { return query(k << 1, l, mid, p); } else { return query(k << 1 | 1, mid + 1, r, p); } } } namespace PST { const int MAXNLOGN = (int) 3e6 + 5; int ch[MAXNLOGN][2], sum[MAXNLOGN]; int root[MAXN], tot, tree_cnt; int newNode() { ++tot; ch[tot][0] = ch[tot][1] = 0; sum[tot] = 0; return tot; } int copyNode(int pre) { ++tot; ch[tot][0] = ch[pre][0]; ch[tot][1] = ch[pre][1]; sum[tot] = sum[pre]; return tot; } void init() { tot = 0; tree_cnt = 0; root[0] = newNode(); } void modify(int &k, int l, int r, int p) { k = copyNode(k); sum[k] += 1; if (l == r) { return; } int mid = (l + r) >> 1; if (p <= mid) { modify(ch[k][0], l, mid, p); } else { modify(ch[k][1], mid + 1, r, p); } } int query(int k, int l, int r, int ql, int qr) { if (k == 0) { return 0; } if (ql <= l && r <= qr) { return sum[k]; } int mid = (l + r) >> 1, res = 0; if (ql <= mid) { res += query(ch[k][0], l, mid, ql, qr); } if (mid < qr) { res += query(ch[k][1], mid + 1, r, ql, qr); } return res; } void insert(int val) { ++tree_cnt; root[tree_cnt] = root[tree_cnt - 1]; modify(root[tree_cnt], 1, n, val); } int query(int l, int r, int x, int y = n) { // tree[l] ~ tree[r], [x, y] if (x > y) { return 0; } return query(root[r], 1, n, x, y) - query(root[l - 1], 1, n, x, y); } } vector G[MAXN]; namespace HLDecomp { int fa[MAXN], size[MAXN], son[MAXN], depth[MAXN], top[MAXN], dfn[MAXN], idfn[MAXN], tot; void dfs(int now) { size[now] = 1; for (int to : G[now]) { if (to == fa[now]) { continue; } fa[to] = now; depth[to] = depth[now] + 1; dfs(to); size[now] += size[to]; if (size[to] > size[son[now]]) { son[now] = to; } } } void dfs2(int now, int tp) { dfn[now] = ++tot; idfn[tot] = now; top[now] = tp; if (son[now] != 0) { dfs2(son[now], tp); } for (int to : G[now]) { if (to == fa[now] || to == son[now]) { continue; } dfs2(to, to); } } void init() { memset(fa, 0, sizeof fa); memset(size, 0, sizeof size); memset(son, 0, sizeof son); memset(depth, 0, sizeof depth); memset(top, 0, sizeof top); memset(dfn, 0, sizeof dfn); tot = 0; dfs(1); dfs2(1, 1); SegTree::init(); PST::init(); for (int i = 1; i <= n; ++i) { PST::insert(idfn[i]); } } void modify(int u) { SegTree::modify(1, 1, n, dfn[u], dfn[u] + size[u] - 1); } int lca(int u, int v) { while (top[u] != top[v]) { if (depth[top[u]] < depth[top[v]]) { swap(u, v); } u = fa[top[u]]; } return depth[u] < depth[v] ? u : v; } int jump(int u) { int res = u; while (fa[top[u]]) { if (SegTree::query(1, 1, n, dfn[top[u]])) { res = top[u]; u = fa[top[u]]; } else { break; } } int l = dfn[top[u]], r = dfn[u]; while (l <= r) { int mid = (l + r) >> 1; if (SegTree::query(1, 1, n, mid)) { res = idfn[mid]; r = mid - 1; } else { l = mid + 1; } } return res; } int query(int u, int v) { int p = lca(u, v); if (SegTree::query(1, 1, n, dfn[p])) { int q = jump(p); return PST::query(dfn[q], dfn[q] + size[q] - 1, min(u, v), max(u, v)) - 1; } else { int res = 0; if (SegTree::query(1, 1, n, dfn[u])) { int q = jump(u); res += PST::query(dfn[q], dfn[q] + size[q] - 1, u); u = fa[q]; } if (SegTree::query(1, 1, n, dfn[v])) { int q = jump(v); res += PST::query(dfn[q], dfn[q] + size[q] - 1, v); v = fa[q]; } res += depth[u] + depth[v] - depth[p] * 2; return res; } } } int main() { int case_cnt; scanf("%d", &case_cnt); while (case_cnt--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) { G[i].clear(); } for (int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } HLDecomp::init(); int m; scanf("%d", &m); while (m--) { int opt; scanf("%d", &opt); if (opt == 1) { int u; scanf("%d", &u); HLDecomp::modify(u); } else { int u, v; scanf("%d%d", &u, &v); printf("%d\n", HLDecomp::query(u, v)); } } } return 0; }