贪心
只能对矩阵的一行/一列进行操作时,应该考虑行与列之间的状态是否相互独立。如果行操作不影响列状态,列操作不影响行状态,则问题可以转化为两个一维子问题:独立考虑完成行/列目标。
注意到本题操作行不影响列的顺序,操作列不影响行的顺序。考虑单独检查是否能操作使得行/列的顺序都符合条件。
对于两个矩阵的每一行维护 set
,如果对于第一个矩阵的每一个 set
,在第二个矩阵中都有完全相同的 set
与之对应,则说明可以通过交换两行的操作将所有行归位,然后只需要在不进行交换两行操作的情况下将列归位即可,同样维护 set
即可。先列后行的归位方式和上述做法没有本质区别。
时间复杂度 $O(nm \log nm)$。
#include<bits/stdc++.h>
using namespace std;
set<int> a[200'005],b[200'005],c[200'005],d[200'005];
bool ans;
int n,m;
void solution(){
cin>>n>>m,ans=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
static int x;
cin>>x;
a[i].emplace(x);
c[j].emplace(x);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
static int x;
cin>>x;
b[i].emplace(x);
d[j].emplace(x);
}
set<set<int>> s;
for(int i=1;i<=n;i++) s.emplace(a[i]);
for(int i=1;i<=n;i++) if(s.find(b[i])==s.end()) ans=0;
s.clear();
for(int i=1;i<=m;i++) s.emplace(c[i]);
for(int i=1;i<=m;i++) if(s.find(d[i])==s.end()) ans=0;
cout<<(ans ? "Yes":"No")<<'\n';
for(int i=1;i<=n;i++) a[i].clear(),b[i].clear();
for(int i=1;i<=m;i++) c[i].clear(),d[i].clear();
}
int T;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--) solution();
return 0;
}