#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>> adj(n+1); unordered_map edgeId; edgeId.reserve(2*(n-1)); edgeId.max_load_factor(0.7f); for (int i = 1; i <= n-1; ++i) { int u, v; cin >> u >> v; adj[u].push_back({v,i}); adj[v].push_back({u,i}); int a = min(u,v), b = max(u,v); long long key = 1LL * a * (n + 1) + b; edgeId[key] = i; } int LOG = 1; while ((1< depth(n+1, 0), parent(n+1, 0); vector> up(LOG, vector(n+1, 0)); // BFS to set parent and depth queue q; parent[1] = 0; depth[1] = 0; q.push(1); vector vis(n+1,0); vis[1]=1; while(!q.empty()){ int u = q.front(); q.pop(); for(auto [v, id] : adj[u]){ if(!vis[v]){ vis[v]=1; parent[v]=u; depth[v]=depth[u]+1; q.push(v); } } } for (int v = 1; v <= n; ++v) up[0][v] = parent[v] ? parent[v] : 0; for (int k = 1; k < LOG; ++k) { for (int v = 1; v <= n; ++v) { int mid = up[k-1][v]; up[k][v] = mid ? up[k-1][mid] : 0; } } auto lift = [&](int v, int k){ for (int i = 0; i < LOG && v; ++i) { if (k & (1< lca = [&](int a, int b){ if (depth[a] < depth[b]) swap(a,b); a = lift(a, depth[a]-depth[b]); if (a == b) return a; for (int k = LOG-1; k >= 0; --k) { if (up[k][a] != up[k][b]) { a = up[k][a]; b = up[k][b]; } } return parent[a]; }; vector posOf(n+1); for (int v = 1; v <= n; ++v) posOf[p[v]] = v; vector ops; ops.reserve(n*n); for (int val = 1; val <= n; ++val) { while (posOf[val] != val) { int u = posOf[val]; int v = val; int w = lca(u, v); int nxt; if (u != w) { nxt = parent[u]; } else { int diff = depth[v] - depth[w] - 1; int child = lift(v, diff); nxt = child; } int a = min(u, nxt), b = max(u, nxt); long long key = 1LL * a * (n + 1) + b; int eid = edgeId[key]; // perform swap on edge (u, nxt) int val_u = p[u]; int val_v = p[nxt]; swap(p[u], p[nxt]); posOf[val_u] = nxt; posOf[val_v] = u; ops.push_back(eid); } } cout << (int)ops.size() << "\n"; for (int id : ops) { cout << 1 << " " << id << "\n"; } } return 0; }