题目链接
题目大意
思路
- 如果全都是升序,不需要变换,直接输出1 1
- 如果可以通过交换两列实现每一行的数都是升序,就直接交换那两行。在这种情况下,可以只交换一次就得到升序列,那么和排完序不一样的地方肯定有且仅有2处。
- 如果当前这一行的数和它排完序后的序列,不一样的数超过2处,则一定不可能只交换一次把序列变成升序,那么就输出 -1。
!!!注意不要开二维数组,需要用vector
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
int x, y;
vector<int> g[500005];
bool check(int idx)
{
//先复制一行
int a[500005];
for (int i = 1; i <= m; i ++ )
{
a[i] = g[idx][i];
}
//排序
sort(a + 1, a + 1 + m);
int cnt = 0;
for (int i = 1; i <= m; i ++ )
{
//对比不一样的地方有几处
if (a[i] != g[idx][i])
{
cnt ++;
//如果只有两处的话,那么x,y就是要交换的那两个数的下标
if (cnt == 1) x = i;
if (cnt == 2) y = i;
}
}
return cnt <= 2;
}
signed main()
{
int t;
cin >> t;
while (t -- )
{
int ff = 0;
scanf("%lld %lld", &n, &m);
for (int i = 1; i <= n; i ++ )
{
g[i].clear();
//为了方便从1调用下标,所以放1个极小数去垫一下
g[i].push_back(-999999);
for (int j = 1; j <= m; j ++ )
{
int x;
scanf("%lld", &x);
g[i].push_back(x);
//判断是否不需要改变,直接输出1 1
if (g[i][j] < g[i][j - 1]) ff = 1;
}
}
//判断是否不需要改变,直接输出1 1
if (ff == 0)
{
printf("1 1\n");
continue;
}
int f = 0;
for (int i = 1; i <= n; i ++ )
{
//把每一行的数据传到函数里面进行判断,传的是第几行
if (check(i) == 0) //如果超过了两处,说明无法改变,直接输出-1
{
f = 1;
printf("-1\n");
break;
}
}
//如果可以改变
if (!f)
{
//那就交换只有两处不同的那一行的那个位置,然后交换这两列
for (int i = 1; i <= n; i ++ )
{
swap(g[i][x], g[i][y]);
}
//最后再判断换了这两列之后,是否符合要求
ff = 0;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
{
if (g[i][j] < g[i][j - 1]) ff= 1;
}
}
if (!ff) cout << x << " " << y << endl;
else cout << -1 << endl;
}
}
return 0;
}