#include using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; if (!(cin >> T)) return 0; while (T--) { int n; cin >> n; vector p(n + 1); for (int i = 1; i <= n; ++i) cin >> p[i]; vector> g(n + 1); vector eu(n), ev(n); for (int i = 1; i <= n - 1; ++i) { int u, v; cin >> u >> v; eu[i] = u; ev[i] = v; g[u].push_back(v); g[v].push_back(u); } // Edge ID matrix for O(1) lookup vector> edgeID(n + 1, vector(n + 1, -1)); for (int i = 1; i <= n - 1; ++i) { int u = eu[i], v = ev[i]; edgeID[u][v] = i; edgeID[v][u] = i; } // Leaf peeling order vector deg(n + 1); for (int i = 1; i <= n; ++i) deg[i] = (int)g[i].size(); vector order; order.reserve(n); queue q; for (int i = 1; i <= n; ++i) { if (deg[i] <= 1) q.push(i); } vector removed(n + 1, false); while (!q.empty()) { int v = q.front(); q.pop(); if (removed[v]) continue; removed[v] = true; order.push_back(v); for (int to : g[v]) { if (!removed[to]) { if (--deg[to] == 1) q.push(to); } } } if ((int)order.size() != n) { for (int i = 1; i <= n; ++i) if (!removed[i]) order.push_back(i); } // Active vertices vector active(n + 1, true); // Token positions vector pos(n + 1); for (int v = 1; v <= n; ++v) { int tok = p[v]; pos[tok] = v; } vector ops; ops.reserve((size_t)n * (size_t)n); vector parent(n + 1); // Process vertices in leaf-peeling order except last for (int idx = 0; idx < n - 1; ++idx) { int v = order[idx]; if (!active[v]) continue; if (p[v] == v) { active[v] = false; continue; } int start = pos[v]; // BFS on active subgraph from start to v fill(parent.begin(), parent.end(), -1); queue qq; parent[start] = start; qq.push(start); while (!qq.empty()) { int x = qq.front(); qq.pop(); if (x == v) break; for (int y : g[x]) { if (!active[y]) continue; if (parent[y] != -1) continue; parent[y] = x; qq.push(y); } } // Reconstruct path from start to v int x = v; vector path; while (x != start) { path.push_back(x); x = parent[x]; } path.push_back(start); reverse(path.begin(), path.end()); // Perform swaps along the path for (int i = 0; i + 1 < (int)path.size(); ++i) { int a = path[i]; int b = path[i + 1]; int eid = edgeID[a][b]; ops.push_back(eid); int tokA = p[a], tokB = p[b]; p[a] = tokB; p[b] = tokA; pos[tokA] = b; pos[tokB] = a; } active[v] = false; } // Output operations cout << ops.size() << "\n"; for (int eid : ops) { cout << 1 << " " << eid << "\n"; } } return 0; }