#include using namespace std; struct Dinic { struct Edge { int to; int rev; int cap; }; vector> graph; vector level; vector iteratorIndex; explicit Dinic(int n) : graph(n), level(n), iteratorIndex(n) {} int addEdge(int from, int to, int cap) { Edge forward{to, static_cast(graph[to].size()), cap}; Edge backward{from, static_cast(graph[from].size()), 0}; graph[from].push_back(forward); graph[to].push_back(backward); return static_cast(graph[from].size()) - 1; } bool bfs(int source, int sink) { fill(level.begin(), level.end(), -1); queue q; level[source] = 0; q.push(source); while (!q.empty()) { int vertex = q.front(); q.pop(); for (const Edge& edge : graph[vertex]) { if (edge.cap > 0 && level[edge.to] < 0) { level[edge.to] = level[vertex] + 1; q.push(edge.to); } } } return level[sink] >= 0; } int dfs(int vertex, int sink, int flow) { if (vertex == sink) { return flow; } for (int& i = iteratorIndex[vertex]; i < static_cast(graph[vertex].size()); i++) { Edge& edge = graph[vertex][i]; if (edge.cap <= 0 || level[vertex] >= level[edge.to]) { continue; } int pushed = dfs(edge.to, sink, min(flow, edge.cap)); if (pushed == 0) { continue; } edge.cap -= pushed; graph[edge.to][edge.rev].cap += pushed; return pushed; } return 0; } int maxFlow(int source, int sink) { int result = 0; while (bfs(source, sink)) { fill(iteratorIndex.begin(), iteratorIndex.end(), 0); while (true) { int pushed = dfs(source, sink, 1'000'000'000); if (pushed == 0) { break; } result += pushed; } } return result; } }; bool solveCase(int n, const vector& r, const vector& c, vector>& answer) { if (n == 1) { answer.assign(1, vector(1, 1)); return true; } if (n == 2) { return false; } vector rowOfValue(n + 1); for (int row = 0; row < n; row++) { rowOfValue[r[row]] = row; } vector> columnsOfValue(n + 1); for (int col = 0; col < n; col++) { columnsOfValue[c[col]].push_back(col); } int rowCapacity = (n - 1) / 2; int source = 0; int labelBase = 1; int rowBase = labelBase + n; int sink = rowBase + n; Dinic dinic(sink + 1); vector> edgeIndex(n + 1, vector(n + 1, -1)); for (int value = 1; value <= n; value++) { dinic.addEdge(source, labelBase + value - 1, static_cast(columnsOfValue[value].size())); for (int rowValue = 1; rowValue <= n; rowValue++) { if (rowValue == value) { continue; } edgeIndex[value][rowValue] = dinic.addEdge(labelBase + value - 1, rowBase + rowValue - 1, n); } } for (int rowValue = 1; rowValue <= n; rowValue++) { dinic.addEdge(rowBase + rowValue - 1, sink, rowCapacity); } if (dinic.maxFlow(source, sink) != n) { return false; } answer.assign(n, vector(n)); for (int row = 0; row < n; row++) { fill(answer[row].begin(), answer[row].end(), r[row]); } vector pointer(n + 1, 0); for (int value = 1; value <= n; value++) { int labelNode = labelBase + value - 1; for (int rowValue = 1; rowValue <= n; rowValue++) { int index = edgeIndex[value][rowValue]; if (index < 0) { continue; } const auto& edge = dinic.graph[labelNode][index]; int used = dinic.graph[edge.to][edge.rev].cap; int row = rowOfValue[rowValue]; for (int i = 0; i < used; i++) { int col = columnsOfValue[value][pointer[value]++]; answer[row][col] = value; } } } return true; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int n; cin >> n; vector r(n), c(n); for (int i = 0; i < n; i++) { cin >> r[i]; } for (int i = 0; i < n; i++) { cin >> c[i]; } vector> answer; if (!solveCase(n, r, c, answer)) { cout << -1 << '\n'; continue; } for (int row = 0; row < n; row++) { for (int col = 0; col < n; col++) { if (col > 0) { cout << ' '; } cout << answer[row][col]; } cout << '\n'; } } return 0; }