JustinTX's picture
Add files using upload-large-folder tool
1fd0050 verified
#include <bits/stdc++.h>
using namespace std;
struct FastScanner {
static constexpr size_t BUFSIZE = 1 << 20;
int idx = 0, size = 0;
char buf[BUFSIZE];
inline char readChar() {
if (idx >= size) {
size = (int)fread(buf, 1, BUFSIZE, stdin);
idx = 0;
if (size == 0) return 0;
}
return buf[idx++];
}
template <class T>
bool readInt(T &out) {
char c;
do {
c = readChar();
if (!c) return false;
} while (c <= ' ');
bool neg = false;
if (c == '-') {
neg = true;
c = readChar();
}
T val = 0;
while (c > ' ') {
val = val * 10 + (c - '0');
c = readChar();
}
out = neg ? -val : val;
return true;
}
};
struct FastOutput {
static constexpr size_t BUFSIZE = 1 << 20;
char buf[BUFSIZE];
size_t idx = 0;
~FastOutput() { flush(); }
inline void flush() {
if (idx) {
fwrite(buf, 1, idx, stdout);
idx = 0;
}
}
inline void pushChar(char c) {
if (idx >= BUFSIZE) flush();
buf[idx++] = c;
}
inline void writeInt(long long x) {
if (x == 0) {
pushChar('0');
return;
}
if (x < 0) {
pushChar('-');
x = -x;
}
char s[24];
int n = 0;
while (x) {
s[n++] = char('0' + (x % 10));
x /= 10;
}
while (n--) pushChar(s[n]);
}
inline void writeStr(const char* s) {
while (*s) pushChar(*s++);
}
inline void writeNewline() { pushChar('\n'); }
};
struct AdjEdge {
int to, id;
};
int main() {
FastScanner fs;
FastOutput fo;
int T;
if (!fs.readInt(T)) return 0;
while (T--) {
int n;
fs.readInt(n);
vector<int> p(n + 1), pos(n + 1);
for (int i = 1; i <= n; i++) {
fs.readInt(p[i]);
pos[p[i]] = i;
}
vector<vector<AdjEdge>> adj(n + 1);
adj.assign(n + 1, {});
for (int i = 1; i <= n - 1; i++) {
int u, v;
fs.readInt(u);
fs.readInt(v);
adj[u].push_back({v, i});
adj[v].push_back({u, i});
}
vector<char> active(n + 1, 1);
vector<int> deg(n + 1, 0);
deque<int> dq;
for (int i = 1; i <= n; i++) {
deg[i] = (int)adj[i].size();
}
for (int i = 1; i <= n; i++) {
if (deg[i] <= 1) dq.push_back(i);
}
vector<int> ops;
ops.reserve(n * n);
vector<char> vis(n + 1, 0);
vector<int> parent(n + 1, 0), parentE(n + 1, 0);
vector<int> st;
st.reserve(n);
auto doSwap = [&](int a, int b, int eid) {
ops.push_back(eid);
int pa = p[a], pb = p[b];
p[a] = pb; p[b] = pa;
pos[pa] = b;
pos[pb] = a;
};
int activeCount = n;
while (activeCount > 1) {
int v = -1;
while (!dq.empty()) {
int x = dq.front();
dq.pop_front();
if (active[x] && deg[x] == 1) {
v = x;
break;
}
}
if (v == -1) break; // should not happen
int start = pos[v];
if (start != v) {
fill(vis.begin(), vis.end(), 0);
st.clear();
st.push_back(v);
vis[v] = 1;
parent[v] = 0;
parentE[v] = 0;
while (!st.empty()) {
int cur = st.back();
st.pop_back();
if (cur == start) break;
for (const auto &e : adj[cur]) {
int to = e.to;
if (!active[to] || vis[to]) continue;
vis[to] = 1;
parent[to] = cur;
parentE[to] = e.id;
st.push_back(to);
}
}
int cur = start;
while (cur != v) {
int nxt = parent[cur];
int eid = parentE[cur];
doSwap(cur, nxt, eid);
cur = nxt;
}
}
active[v] = 0;
activeCount--;
int neigh = 0;
for (const auto &e : adj[v]) {
if (active[e.to]) {
neigh = e.to;
break;
}
}
if (neigh) {
deg[neigh]--;
if (deg[neigh] == 1 && activeCount > 1) dq.push_back(neigh);
}
deg[v] = 0;
}
fo.writeInt((long long)ops.size());
fo.writeNewline();
for (int eid : ops) {
fo.writeInt(1);
fo.pushChar(' ');
fo.writeInt(eid);
fo.writeNewline();
}
}
fo.flush();
return 0;
}