| #include <iostream> |
| #include <vector> |
| #include <numeric> |
| #include <algorithm> |
|
|
| using namespace std; |
|
|
| |
| struct Edge { |
| int u, v, id; |
| }; |
|
|
| int n; |
| vector<int> p; |
| vector<vector<int>> adj; |
| vector<Edge> edges; |
| vector<int> tin, tout; |
| int timer; |
|
|
| |
| void dfs_tin(int u, int parent) { |
| tin[u] = ++timer; |
| for (int idx : adj[u]) { |
| int v = (edges[idx].u == u) ? edges[idx].v : edges[idx].u; |
| if (v != parent) { |
| dfs_tin(v, u); |
| } |
| } |
| tout[u] = timer; |
| } |
|
|
| |
| bool is_ancestor(int u, int v) { |
| return tin[u] <= tin[v] && tout[u] >= tout[v]; |
| } |
|
|
| |
| bool wants_to_move(int u_curr, int v_next, int val) { |
| int target = val; |
| |
| if (is_ancestor(u_curr, v_next)) { |
| |
| return is_ancestor(v_next, target); |
| } else { |
| |
| return !is_ancestor(u_curr, target); |
| } |
| } |
|
|
| void solve() { |
| if (!(cin >> n)) return; |
| p.assign(n + 1, 0); |
| for (int i = 1; i <= n; ++i) cin >> p[i]; |
| |
| adj.assign(n + 1, vector<int>()); |
| edges.clear(); |
| for (int i = 0; i < n - 1; ++i) { |
| int u, v; |
| cin >> u >> v; |
| edges.push_back({u, v, i + 1}); |
| adj[u].push_back(i); |
| adj[v].push_back(i); |
| } |
|
|
| tin.assign(n + 1, 0); |
| tout.assign(n + 1, 0); |
| timer = 0; |
| |
| dfs_tin(1, 0); |
|
|
| vector<vector<int>> ops; |
| |
| while (true) { |
| bool sorted = true; |
| for(int i = 1; i <= n; ++i) { |
| if(p[i] != i) { |
| sorted = false; |
| break; |
| } |
| } |
| if (sorted) break; |
|
|
| vector<int> type1; |
| vector<int> type2; |
|
|
| for (int i = 0; i < edges.size(); ++i) { |
| int u = edges[i].u; |
| int v = edges[i].v; |
| int pu = p[u]; |
| int pv = p[v]; |
| |
| bool u_wants_v = wants_to_move(u, v, pu); |
| bool v_wants_u = wants_to_move(v, u, pv); |
|
|
| if (u_wants_v && v_wants_u) { |
| type1.push_back(i); |
| } else if (u_wants_v || v_wants_u) { |
| type2.push_back(i); |
| } |
| } |
|
|
| if (type1.empty() && type2.empty()) break; |
|
|
| vector<bool> matched(n + 1, false); |
| vector<int> current_op_edges; |
|
|
| |
| for (int idx : type1) { |
| int u = edges[idx].u; |
| int v = edges[idx].v; |
| if (!matched[u] && !matched[v]) { |
| matched[u] = true; |
| matched[v] = true; |
| current_op_edges.push_back(edges[idx].id); |
| swap(p[u], p[v]); |
| } |
| } |
|
|
| |
| if (ops.size() % 2 != 0) { |
| reverse(type2.begin(), type2.end()); |
| } |
|
|
| |
| for (int idx : type2) { |
| int u = edges[idx].u; |
| int v = edges[idx].v; |
| if (!matched[u] && !matched[v]) { |
| matched[u] = true; |
| matched[v] = true; |
| current_op_edges.push_back(edges[idx].id); |
| swap(p[u], p[v]); |
| } |
| } |
| |
| if (current_op_edges.empty()) break; |
|
|
| ops.push_back(current_op_edges); |
| } |
|
|
| cout << ops.size() << "\n"; |
| for (const auto& op : ops) { |
| cout << op.size(); |
| for (int id : op) cout << " " << id; |
| cout << "\n"; |
| } |
| } |
|
|
| int main() { |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
| int t; |
| if (cin >> t) { |
| while (t--) { |
| solve(); |
| } |
| } |
| return 0; |
| } |