贪心

只能对矩阵的一行/一列进行操作时,应该考虑行与列之间的状态是否相互独立。如果行操作不影响列状态,列操作不影响行状态,则问题可以转化为两个一维子问题:独立考虑完成行/列目标

注意到本题操作行不影响列的顺序,操作列不影响行的顺序。考虑单独检查是否能操作使得行/列的顺序都符合条件。

对于两个矩阵的每一行维护 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;
}
最后修改:2025 年 06 月 26 日
如果觉得我的文章对你有用,请随意赞赏