思路

本来想着这是一道最大匹配的水题,没想到忘了变量初始化WA了。
用匈牙利算法水过,题意大概是这个意思,假设我们有两个点集X和Y,
那么输入就可以转化为二分图两边点的连线情况。
交换行列式的过程,实际上是固定一个点集,另外一个点集内部在交换位置(讲得很抽象,画图试试?)
然后就可以想到只要每个点都有与之匹配的点就可以完成这个交换了,
所以是二分图最大匹配。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=205;
struct X{
    int next,to;
}e[maxn*maxn];

int t,n,flag,a[maxn][maxn];
int head[maxn],cnt;
int match[maxn],vis[maxn];


void addedge(int from,int to){
    e[++cnt].next=head[from];
    e[cnt].to=to;
    head[from]=cnt;
}

bool check(int x){
    for(int i=head[x];i;i=e[i].next){
        int to=e[i].to;
        if(!vis[to]){
            vis[to]=1;
            if(!match[to]||check(match[to])){
                match[to]=x;
                return true;
            }    
        }
    }
    return false;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--){
        cin>>n;
        flag=1,cnt=0;
        memset(head,0,sizeof(head));
        memset(match,0,sizeof(match));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>a[i][j];
                if(a[i][j]){
                    addedge(i,j);
                //    addedge(j,i);
                }
            }
        }
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof(vis));
            if(!check(i)){
                flag=0;
                break;
            }
        }
        if(flag) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}