#include using namespace std; int n; vector p; vector> edges; map, int> edgeIdx; vector parent, depth, in, out; vector> children; int timer; bool in_subtree(int v, int x) { return in[v] <= in[x] && in[x] < out[v]; } void dfs(int u, int par) { parent[u] = par; in[u] = timer++; for (int v : children[u]) { if (v == par) continue; depth[v] = depth[u] + 1; dfs(v, u); } out[u] = timer; } vector get_upward_matching() { vector> cand; for (int v = 2; v <= n; ++v) { int u = parent[v]; if (u == 0) continue; if (!in_subtree(v, p[v])) { cand.emplace_back(u, v); } } sort(cand.begin(), cand.end(), [](const pair& a, const pair& b) { return depth[a.second] > depth[b.second]; }); vector used(n+1, false); vector matching; for (auto& e : cand) { int u = e.first, v = e.second; if (!used[u] && !used[v]) { used[u] = used[v] = true; matching.push_back(edgeIdx[{u, v}]); } } return matching; } vector get_downward_matching() { vector> cand; for (int v = 2; v <= n; ++v) { int u = parent[v]; if (u == 0) continue; if (in_subtree(v, p[u])) { cand.emplace_back(u, v); } } sort(cand.begin(), cand.end(), [](const pair& a, const pair& b) { return depth[a.second] > depth[b.second]; }); vector used(n+1, false); vector matching; for (auto& e : cand) { int u = e.first, v = e.second; if (!used[u] && !used[v]) { used[u] = used[v] = true; matching.push_back(edgeIdx[{u, v}]); } } return matching; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { cin >> n; p.resize(n+1); for (int i = 1; i <= n; ++i) cin >> p[i]; edges.resize(n); edgeIdx.clear(); vector> adj(n+1); for (int i = 1; i < n; ++i) { int u, v; cin >> u >> v; edges[i] = {u, v}; edgeIdx[{u, v}] = i; edgeIdx[{v, u}] = i; adj[u].push_back(v); adj[v].push_back(u); } // prepare rooted tree parent.assign(n+1, 0); depth.assign(n+1, 0); in.assign(n+1, 0); out.assign(n+1, 0); children = adj; // temporary, will be refined // rebuild children lists (excluding parent) for (int i = 1; i <= n; ++i) children[i].clear(); timer = 0; function dfs2 = [&](int u, int par) { parent[u] = par; in[u] = timer++; for (int v : adj[u]) { if (v == par) continue; depth[v] = depth[u] + 1; children[u].push_back(v); dfs2(v, u); } out[u] = timer; }; dfs2(1, 0); vector> operations; bool up_next = true; while (true) { bool sorted = true; for (int i = 1; i <= n; ++i) if (p[i] != i) { sorted = false; break; } if (sorted) break; vector matching; if (up_next) matching = get_upward_matching(); else matching = get_downward_matching(); if (matching.empty()) { up_next = !up_next; // try the other phase continue; } for (int idx : matching) { auto [u, v] = edges[idx]; swap(p[u], p[v]); } operations.push_back(matching); up_next = !up_next; } cout << operations.size() << "\n"; for (auto& op : operations) { cout << op.size(); for (int idx : op) cout << " " << idx; cout << "\n"; } } return 0; }