教育场129 c题

c.双倍排序

题意

给定两个数组 a 和 b,均由 n 个整数组成。

在一个步骤中,您可以选择两个索引 i 和 j (1≤i,j≤n; i≠j) 并将 ai 与 aj 和 bi 与 bj 交换。 您必须在两个阵列中执行交换。

您最多可以执行 10^4 次移动(可能为零)。 你可以让两个数组最后都按非递减顺序排序吗? 如果可以,请打印任何使两个数组都排序的移动序列。

输入

第一行为测试数量t (1≤t≤100) 。

第二行为长度n (2≤n≤100) ,然后是 a1,a2,…,an (1≤ai≤n) ,b1,b2,…,bn(1≤bi≤n)

输出

对于每个测试用例,打印答案。 如果不可能在最多 104 次移动中使两个数组按非递减顺序排序,则打印 -1。 否则,首先打印移动次数 k (0≤k≤10^4)。 然后为每一步打印 i 和 j (1≤i,j≤n; i≠j)。

如果有多个答案,则打印其中任何一个。 您不必尽量减少移动次数。

题目分析

重写cmp的排序,然后一一比较是否无解,最后根据排序后的结果寻找输出位置(注意:cmp不能加等于号!!)

#include<bits/stdc++.h>
using namespace std;
struct Node {
	int a,b;
};
bool cmp(Node x,Node y) {
	if(x.a!=y.a) {
		return x.a <= y.a;
	}
	return x.b <= y.b;
}
Node no[1007],pre[1007];
pair<int,int>ans[30000];
int main() {
	int tc;
	cin >> tc;
	while(tc--) {
		int n;
		cin >> n;
		for(int i = 1 ; i <= n ; i++)
			cin >> no[i].a;

		for(int i = 1 ; i <= n ; i++)
			cin >> no[i].b;

		for(int i = 1 ; i <= n ; i++)
			pre[i] = no[i];

		sort(no+1,no+n+1,cmp);
		bool flag = 1;
		for(int i = 2 ; flag && i <= n ; i++) {
			if(no[i].a < no[i-1].a || no[i].b < no[i-1].b ) {
				flag = 0;
			}
		}
		if(!flag) {
			cout << -1 << endl;
			continue;
		}
		int cnt = 0;
		for(int i = 1 ; i <= n ; i++) {
			if(no[i].a != pre[i].a || no[i].b != pre[i].b) {
				for(int j = i+1 ; j <= n ; j++) {
					if(pre[j].a == no[i].a && pre[j].b == no[i].b) {
						Node t = pre[j];
						pre[j] = pre[i];
						pre[i] = t;
						ans[++cnt] = {i,j};
					}
				}
			}
		} 
		cout << cnt << endl;
		for(int i = 1 ; i <= cnt ; i++) {
			cout << ans[i].first << " " << ans[i].second << endl;
		}
	}
}
posted @ 2022-05-25 10:18  seekerHeron  阅读(20)  评论(0)    收藏  举报